You are on page 1of 13

TECHNICAL UNIVERSITY OF MOLDOVA

FACULTY OF COMPUTERS, INFORMATICS AND MICROELECTRONICS


SPECIALITY SOFTWARE ENGINEERING

Report
on
Probability & Statistics

Laboratory Work nr.1

Performed: st. gr.


FAF-212
Maia
Zaica

Verified: Cristofor Fiștic

Chişinău 2021
Short theory on laboratory work:
Python is a general purpose, dynamic, high-level, and interpreted programming language. It supports
Object Oriented programming approach to develop applications. It is simple and easy to learn and provides
lots of high-level data structures.
 Syntax and Semantic
Python is meant to be an easily readable language. Its formatting is visually uncluttered, and it often uses
English keywords where other languages use punctuation. Unlike many other languages, it does not
use curly brackets to delimit blocks, and semicolons after statements are allowed but are rarely, if ever, used.
It has fewer syntactic exceptions and special cases than C or Pascal.
 Indentation
Python uses whitespace indentation, rather than curly brackets or keywords, to delimit blocks. An
increase in indentation comes after certain statements; a decrease in indentation signifies the end of the
current block. Thus, the program's visual structure accurately represents the program's semantic
structure. This feature is sometimes termed the off-side rule, which some other languages share, but in most
languages indentation does not have any semantic meaning. The recommended indent size is four spaces.
Variable is a name that is used to refer to memory location. Python variable is also known as an identifier
and used to hold value.

LABORATORY WORK Nr.1

Problem condition:
1. Poker Hands In the card game poker, a hand consists of five cards and are ranked, from lowest to highest, in
the following way:
 High Card: Highest value card.
 One Pair: Two cards of the same value.
 Two Pairs: Two different pairs.
 Three of a Kind: Three cards of the same value.
 Straight: All cards are consecutive values.
 Flush: All cards of the same suit.
 Full House: Three of a kind and a pair.
 Four of a Kind: Four cards of the same value.
 Straight Flush: All cards are consecutive values of the same suit.
 Royal Flush: Ten, Jack, Queen, King, Ace, in the same suit.

The cards are valued in the order:


2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, King, Ace.

If two players have the same ranked hands then the rank made up of the highest value wins; for example, a pair of
eights beats a pair of fives (see example 1 below). But if two ranks tie, for example, both players have a pair of
queens, then the highest cards in each hand are compared (see example 4 below); if the highest cards tie then the next
highest cards are compared, and so on.

Consider the following five hands dealt to two players:


Hand Player 1 Player 2 Winner
1 5H 5C 6S 7S KD 5H 5C 6S 7S KD Player 2
Pair of Fives Pair of Fives
2 5D 8C 9S JS AC 2C 5C 7D 8S QH Player 1
Highest card Ace Highest card Queen
3 2D 9C AS AH AC 3D 6D 7D TD QD Player 2
Three Aces Flush with Diamonds
4 4D 6S 9H QH QC 3D 6D 7H QD QS Player 1
Pair of Queens Pair of Queens
Highest card Nine Highest card Seven
5 2H 2D 4C 4D 4S 3C 3D 3S 9S 9D Player 1
Full House Full House
With Three Fours with Three Threes

The file poker.txt(in the zip file from email), contains one-thousand random hands dealt to two players. Each line of
the file contains ten cards (separated by a single space): the first five are Player 1's cards and the last five are Player 2's
cards. You can assume that all hands are valid (no invalid characters or repeated cards), each player's hand is in no
specific order, and in each hand there is a clear winner.

How many hands does Player 1 win?

Topic: List. Functions. Return Statements. For Loops. If statements.

Laboratory work processing:

Analysis
If we can quantify each hand into an array of tuples we can quickly compare each hand and determine a winner or a
tie.
The first tuple would consist between 2 and 5 elements representing the frequency of card values sorted in descending
order. The second tuple would consist of the same number of elements as the first but describe the value sorted and
weighted by frequency in descending order.
Let’s check out how this would look for a few typical hands for both players:
p1 = TH 6H 9H QH JH [(1, 1, 1, 1, 1), (12, 11, 10, 9, 6)], score = 0
p2 = 9H 4D JC KS JS [(2, 1, 1, 1), (11, 13, 9, 4)], score = 1

p1 = 7C 7S KC KS JC [(2, 2, 1), (13, 7, 11)], score = 2


p2 = 7H 7D KH KD 9S [(2, 2, 1), (13, 7, 9)], score = 2

Ties in similar scores are broken by checking the second tuple

By simply comparing hands as p1>p2 we can determine the winner between the two players. The only complication
left is to calculate and rank straights and flushes.

from collections import Counter


hands = (line.split() for line in open('poker'))

values = {r:i for i,r in enumerate('23456789TJQKA', 2)}


straights = [(v, v-1, v-2, v-3, v-4) for v in range(14, 5, -1)] + [(14, 5, 4, 3, 2)]
ranks = [(1,1,1,1,1),(2,1,1,1),(2,2,1),(3,1,1),(),(),(3,2),(4,1)]

def hand_rank(hand):
score_object = zip(*sorted(((v, values[k]) for k,v in Counter(x[0] for x in
hand).items()), reverse=True))
score = list(score_object)
score[0] = ranks.index(score[0])
if len(set(card[1] for card in hand)) == 1:
score[0] = 5 # flush
if score[1] in straights:
score[0] = 8 if score[0] == 5 else 4 # str./str. flush
return score

print("Player 1 wins", sum(hand_rank(hand[:5]) > hand_rank(hand[5:]) for hand in hand

Problem condition:
2. I bet my life on this one
Are you still in the mood for betting ? Now let’s play something more interesting and serious! Let's play some
Russian roulette. Here's the deal. I have a revolver with a 6 slots barrel and only 2 bullets. Now I put the bullets into
the revolver in adjacent slots, spin the barrel and hand you the gun. You point the gun to your head. You pull the
trigger and ... Click! you're still alive.
Congratulations but the game is not over yet. You have to pull the trigger one last time. Now you have two choices.
1 You spin the barrel afterwards you pull the trigger. 2 You pull the trigger without spinning. Luckily you have some
time and a computer with you in your bag so you can simulate the current situation such that you can choose the
correct choice.
Your assignment is to calculate the probability for both cases and after you've found the probability for the initial
conditions you need also to find out what are the probabilities in case the bullets are not adjacent. Now you need to
calculate the same probabilities but in case when you have 2 bullets and the gun has a 5 slots barrel. You have to
present the result for 8 different outcomes. Good luck staying alive.

Laboratory work processing:

1. 6 slots barrel
 adjacent slots
4 2
At first there is = probability to stay alive, after clicking once and managing to stay alive if we choose to spin we
6 3
4
get chance to stay alive, but if the cylinder is not spun, the key to calculating the odds is the clue that the rounds
6
are located in adjacent chambers. This means that there are two rounds next to each other, followed by four blank
spaces. We heard a click on the first pull, which means we are somewhere in the run of these four blank locations. Of
these four spaces, only one of them is followed by a round. There is a one chance in four that we are at this bad
3
location, and it means that there is a
chance that the chamber to come is empty. By not spinning again there is a
4
2
75% chance we will live. Compared to the chances are bigger if we don’t spin.
3

 Not adjacent
Let's calculate what would happen if they were placed in random locations. There are 6 choose 2 ways (fifteen) that
two rounds can be placed into the cylinders. Without loss of generality, here they are:

o There are six possible ways the cartridges can be loaded adjacent.
o There are six possible ways the cartridges can be loaded one apart.
o There are three possible ways the cartridges can be loaded opposite.

3
We already know that, in the adjacent case, there is a chance that the chamber following an empty chamber is also
4
6
empty. The adjacent condition occurs . We multiply these probabilities together. We next add the similar
15
conditional probabilities for the six one-apart cases (where two out of the four empty cells has a following empty
chamber), and finally for the three opposite cases (again where two out of the four empty cells has a following emoty
chamber).
Pr¿ ( 156 × 34 )+( 156 × 24 )+( 156 × 24 )
3 1 1 3
Pr¿ + + =
10 5 10 5
3
There is a 60% chance ( ) we will survive a second trigger pull with two rounds in arbitrary locations.
5
This is slightly lower than the 66.7% survival chance that will happen with a re-spin, so if the two rounds are loaded
randomly it's better to ask for a re-spin.

2. 5 slots barrel
 Adjacent slots
3 1
After surviving once, with spinning we’d have the probability chance to live, we have probability of of choosing
5 3
2
a slot with a loaded slot, which means we have chance we choose the ones with blank spaces so choosing spinning
3
would be a better choice.
 Random rounds
o There are five possible ways the cartridges can be loaded adjacent.
o There are five possible ways the cartridges can be loaded one apart.
2
We already know that, in the adjacent case, there is a chance that the chamber following an empty chamber is also
3
5
empty. The adjacent condition occurs . We multiply these probabilities together. We next add the similar
10
conditional probabilities for the five one-apart cases (where one out of the three empty cells has a following empty
chamber).
Pr¿ ( 105 × 32 )+( 105 × 13 )
1 1 1
Pr¿ + =
3 6 2

There is a 50% chance we will survive a second trigger pull with two rounds in arbitrary locations.
This is slightly lower than the 60% survival chance that will happen with a re-spin, so if the two rounds are loaded
randomly it's better to ask for a re-spin.

We’ll make a list bullet that include the number of slots in the cylinder and the bullets placement.
The user we’ll choose from the options given.
choice = bullet[int(input()) - 1]

Will pull the trigger and see if he survives. It will be done with the help of choice() method returns a randomly
selected element from the specified sequence.

The sequence can be a string, a range, a list, a tuple or any other kind of sequence. In our case from the list we made.

If the user survives. We go further to try our luck again. The user again has to input the same option and depending on
it will be asked to choose to spin the barrel or not and told to do so until the one with bigger chance of surviving is
chosen. Then we pull the trigger for the second time and see if we survived.
Probability

cylinder
Slots/
Bullets
Placement
Advice
Spinning Not Spinning

4 3
Adjacent Don’t Spin
6 4

6 slots barrel
One apart 4 2
Spin
6 4

4 2
Opposite Spin
6 4

3 2
Adjacent Don’t Spin
5 3
5 slots barrel

3 1
One apart Spin
5 3

import random

bullet =[['Bye :)', 'Bye :)', 'Yay!', 'Yay!', 'Yay!', 'Yay!'],


# 6 slots barrel adjacent bullet placement
['Bye :)', 'Yay!', 'Bye :)', 'Yay!', 'Yay!', 'Yay!'],
# 6 slots barrel one apart bullet placement
['Bye :)', 'Yay!', 'Yay!', 'Bye :)', 'Yay!', 'Yay!'],
# 6 slots barrel opposite bullet placement
['Bye :)', 'Bye :)', 'Yay!', 'Yay!', 'Yay!'],
# 5 slots barrel adjacent
['Bye :)', 'Yay!', 'Bye :)', 'Yay!', 'Yay!']]
# 5 slots barrel one apart

print('''
Choose 1 for a 6 slots barrel with the bullets put into the revolver in adjacent slots
Choose 2 for a 6 slots barrel with the bullets put into the revolver one apart
Choose 3 for a 6 slots barrel with the bullets put into the revolver in opposite slots
Choose 4 for a 5 slots barrel with the bullets put into the revolver in adjacent slots
Choose 5 for a 5 slots barrel with the bullets put into the revolver one apart
''')
choice = bullet[int(input()) - 1]
click = random.choice(choice)
print(input("Press enter to pull the trigger\n>"))
print(click)
index = choice.index(click)
result = choice[index+1]

if (click == 'Yay!'):
print("Choose same as before")
choice = int(input()) - 1

if choice == 0:
while input('Spin the barrel (y / n)? ') == 'y':
print("Think again! That way you'll have 66.7% chance to live")
print("Good luck! You have 75% chance to live")
print(input("Press enter to pull the trigger\n>"))
print(result)
elif choice == 1:
while input('Spin the barrel (y / n)? ') == 'n':
print("Think again! You have 50% chance to live")
print("Good luck! You have 66.7% chance to live")
print(input("Press enter to pull the trigger\n>"))
type = bullet[choice]
second_try = random.choice(type)
print(second_try)
elif choice == 2:
while input('Spin the barrel (y / n)? ') == 'n':
print("Think again! You have 50% chance to live")
print("Good luck! You have 66.7% chance to live")
print(input("Press enter to pull the trigger\n>"))
type = bullet[choice]
second_try = random.choice(type)
print(second_try)
elif choice == 3:
while input('Spin the barrel (y / n)? ') == 'y':
print("Think again! That way you'll have 60% chance to live")
print("Good luck!!!! You have 66.7% chance to live")
print(input("Press enter to pull the trigger\n>"))
print(result)
elif choice == 4:
while input('Spin the barrel (y / n)? ') == 'n':
print("Think again! You have 33.3% chance to live")
print("Good luck! You have 60% chance to live")
type = bullet[choice]
second_try = random.choice(type)
print(second_try)

Problem condition:
3. 21 Game
Ivan plays the following game, loosely based on the card game "21". Ivan starts with 0 points and draws numbers
while he has less than k points. During each draw, he gains an integer number of points randomly from the range
[1,maxPts], where maxPts is an integer. Each draw is independent and the outcomes have equal probabilities. Ivan
stops drawing numbers when he gets k or more points. Return the probability that Ivan has n or fewer points.
Example 1:
Input: n = 10, k = 1, maxPts = 10
Output: 1.00000
Explanation: Ivan gets a single card, then stops.
Example 2:
Input: n = 6, k = 1, maxPts = 10
Output: 0.60000
Explanation: Ivan gets a single card, then stops. In 6 out of 10 possibilities, he is at or below 6 points. Example 3:
Input: n = 21, k = 17, maxPts = 10
Output: 0.73278

Train of thought : dynamic programming


in the title, three variables are provided : n, k, maxPts

n: Here is equivalent to a boundary, the requirements are required to finally extract numbers and the comparison
with n
k: here is a condition under which you can continue to extract numbers.
maxPts: Number face value, that is, the number extracted, is within 1 to maxPts

Example 1:

n = 10, k = 1, maxPts = 10

because Ivan is 0 at the beginning, at this time 0 < k = 1, so now he can continue to draw numbers, and the face
value of the numbers is in the range of [1, 10]. require digits to be extracted and less than n (n=10), probability it's
quite obvious here that the probability is 1, because the face value is in [1, 10], no matter which number is drawn, it
will be larger than k, meet the conditions that are not in the extraction, and the final sum will also fall in [1, 10]
between, the result here must be less than or equal to n, so the probability is 1.

Example 2:

n = 6, k = 1, maxPts = 10

what's changed here is n value. the case of extraction is also shown in the example. 1, at face value [1, 10] no matter
which number is drawn, it cannot be extracted again. , because and greater than k, the final and the same fall on [1,
10] between. n 6 [1, 6] n 60% 0.6

We’ll write a function called round_up() that implements the “rounding up” strategy:

def round_up(n, decimals=0):


multiplier = 10 ** decimals
return math.ceil(n * multiplier) / multiplier
You may notice that round_up() looks a lot like truncate(). First, the decimal point in n is shifted the correct
number of places to the right by multiplying n by 10 ** decimals. This new value is rounded up to the nearest integer
using math.ceil(), and then the decimal point is shifted back to the left by dividing by 10 ** decimals.

This pattern of shifting the decimal point, applying some rounding method to round to an integer, and then shifting the
decimal point back will come up over and over again as we investigate more rounding methods. This is, after all, the
mental algorithm we humans use to round numbers by hand.

Let’s look at how well round_up() works for different inputs:

import math

class Solution:
def new21Game(self, n: int, k: int, maxPts: int) -> float:
dp = [0.0] * (k + maxPts)
for i in range(k, min(n, k + maxPts - 1) + 1):
dp[i] = 1.0
dp[k - 1] = float(min(n - k + 1, maxPts) / maxPts)
for i in range(k - 2, -1, -1):
dp[i] = dp[i + 1] - (dp[i + maxPts + 1] - dp[i + 1]) / maxPts

return dp[0]

def round_up(n, decimals=0):


multiplier = 10 ** decimals
return math.ceil(n * multiplier) / multiplier

n, k, maxPts = int(input()), int(input()), int(input())


output = Solution()
print(round_up(output.new21Game(n, k, maxPts), 5))
Problem condition:
4. Birthday attack
This exercise aims to introduce you to a very basic concept of hashing algorithms, how they work, why they are useful
and what are their weaknesses. And along the way you'll pick up the principle behind the flaw of hashing functions.
Do you remember at some lesson I explained to you about the birthday paradox that was used creating birthday attack.
Now you're gone make the birthday attack with the md5 hashing algorithm. Your task ahead is to find collisions for
this algorithm, (only for the first 40 bits of the hash, aka first 10 hex characters).
You have to write a small program that would eventually find a collision for the first 40 bits generated by the md5
algorithm.

Tip: Cracking the first 40 bits usually takes a few seconds (might get to a dozen of seconds), hence I recommend for
starters to find the collision only for the first 20 bits. Once it is working you can increase the number.

Solution:
Birthday attack is a type of cryptographic attack that belongs to a class of brute force attacks. It exploits the
mathematics behind the birthday problem in probability theory. The success of this attack largely depends upon the
higher likelihood of collisions found between random attack attempts and a fixed degree of permutations, as described
in the birthday paradox problem. 
Can be generalized to a group of n people, where P(n) is the probability of at least two people sharing a birthday:
365 !
P(n)=1−
(365−n ) ! ∙ 365n
This attack can be used to abuse communication between two or more parties. The attack depends on the higher
likelihood of collisions found between random attack attempts and a fixed degree of permutations (pigeonholes). The
Pigeonhole principle states that if n items are put into m containers, with n > m, then at least one container must
contain more than one item. With a birthday attack, it is possible to find a collision of a hash function in √ 2n=2n /2 ,
with 2n being the classical preimage resistance security.

A hash function is a one-way function with a fixed output size. That is, the output has the same size and it is difficult
to find two distinct input chucks, which give the same output.
A hash function is any function that can be used to map data of arbitrary size to fixed-size values.
Probably the best know example of a hash-function is the MD5. It was designed to be used as a cryptographic hash
function, but has been found to have many vulnerabilities.

Assuming a non leap year(hence 365 days).  We generate a certain number of people. Getting the first 10 hexadecimal
characters we compare to get the number of collisions.
import random
import hashlib

people = 1000
randomlist = {}
count = 0
for i in range(people):
n = str(random.randint(0, 365))
result = hashlib.md5(n.encode()).hexdigest()
result = result[:10]
if result in randomlist:
count += 1
else:
randomlist[result] = n

print(f"Collisions found out of {people} people: {count}")

from random import randint


from datetime import datetime, timedelta
from multiprocessing import Pool, cpu_count

import matplotlib.pyplot as plt

def random_birthdays(number_of_people):
first_day_of_year = datetime(1995, 1, 1)
return [first_day_of_year + timedelta(days=randint(1, 365))
for _ in range(number_of_people)]

def determine_probability(number_of_people, run_amount=1000):


dups_found = 0
print(f"Generating day {number_of_people}")
for _ in range(run_amount):
birthdays = random_birthdays(number_of_people)
duplicates = set(x for x in birthdays if birthdays.count(x) > 1)
if len(duplicates) >= 1:
dups_found += 1

return number_of_people, dups_found/run_amount * 100

def plot_yearly_probabilities(max_people, vertical_markers=(23, 70)):


with Pool(processes=cpu_count()) as p:
percent_chances = p.map(determine_probability, range(max_people))

plt.plot([z[1] for z in sorted(percent_chances, key=lambda x: x[0])])

plt.xlabel("Number of people")
plt.ylabel('Chance of sharing a birthday (Percentage)')

for marker in vertical_markers:


if max_people >= marker:
plt.axvline(x=marker, color='red')

plt.savefig("birthday_paradox.png")

if __name__ == '__main__':
plot_yearly_probabilities(100)

Problem condition:
5. Coin Toss
How much should I bet ? Are you in for some betting ? In this game there are some rules: a fair coin will be tossed
until the first time it comes up heads. If this occurs on the jth toss you are paid 2 to power j dollars. You are sure to
win at least 2 dollars so you should be willing to pay to play this game, but how much ? Few people would pay as
much as 10 dollars to play this game. See if you can decide, by simulation, a reasonable amount that you would be
willing to pay, per game, if you will be allowed to make a large number of plays of the game. Does the amount that
you would be willing to pay per game depend upon the number of plays that you will be allowed ?
Solution:
A paradox involving the game of flipping a coin where the expected payoff of the theoretical lottery game approaches
infinity but nevertheless seems to be worth only a very small amount to the participants.

1 k 1 1 1
Expected value: E=∑ ∙2 = ∙2+ ∙ 4+ ∙ 8+…
k=1 2
k
2 4 8
¿ 1+1+1+…
¿∞

The simplest way to try and resolve the paradox to find a fair price for the game was done by Georges-Louis Leclerc,
Comte de Buffon, a French mathematician. He simply ran the experiment himself a total of 2,048 times.
We can calculate the expected winnings based off this experiment. Be careful when calculating the probabilities. For
example, the probability of rolling a tails on the first flip based off this experiment (the experimental probability) is
1061 1
, not , because Buffon got this result 1,061 out of the 2,048 trials he did. So the expected winnings based off
2048 2
this experiment is
1061 494 232 137 56 29 25 8 6
∙ ($ 2)+ ∙ ( $ 4 )+ ∙ ( $ 8)+ ∙ ( $ 16 )+ ∙ ( $ 32 ) + ∙ ( $ 64 )+ ∙ ( $ 128 ) + ∙ ( $ 256 )+ ∙(
2048 2048 2048 2048 2048 2048 2048 2048 2048
. One should expect to pay about $10 to play this game, based off this experiment.

import random
This module implements pseudo-random number generators for various distributions.

For integers, there is uniform selection from a range. For sequences, there is uniform selection of a random element, a
function to generate a random permutation of a list in-place, and a function for random sampling without replacement.

class Game:

Python is an object oriented programming language. Almost everything in Python is an object, with its properties and
methods. A Class is like an object constructor, or a "blueprint" for creating objects.

Classes provide a means of bundling data and functionality together. Creating a new class creates a new type of object,
allowing new instances of that type to be made. Each class instance can have attributes attached to it for maintaining
its state. Class instances can also have methods (defined by its class) for modifying its state.

We create a class named Game.

Which include:

__init__() function. The __init__() function is called automatically every time the class is being used to create a new
object. It assigns values to object properties, or other operations that are necessary to do when the object is being
created. The self parameter is a reference to the current instance of the class, and is used to access variables that
belong to the class.

__repr__ () function - a special method used to represent a class’s objects as a string. __repr__ is called by the repr()
built-in function. You can define your own string representation of your class objects using the __repr__ method.

Also will insert a function for tossing the coin, it counts how many Tails straight we get. With random.randint(0, 1)
we get random values 0 it means we got Tail and we continue tossing, once we get 1 that is Head it stops.

We create a function main(). The "while true" loop in python runs without any conditions until the break statement
executes inside the loop. The user needs to input a positive number for fee, with the while loop the user is asked if he
want to continue to bet. It will display how much the user wins and how much the bank wins.
It checks if the __name__ attribute of the Python script is "__main__" . In other words, if the program itself is
executed, the attribute will be __main__ , so the program will be executed (in this case the main() function).

The condition if __name__ == ‘__main__’ is used in a Python program to execute the code inside the if statement
only when the program is executed directly by the Python interpreter. When the code in the file is imported as a
module the code inside the if statement is not executed. A boilerplate code that protects users from accidentally
invoking the script when they didn't intend to.

import random

class Game:
def __init__(self, fee):
self.turn = 0
self.coin = None
self.player_money = 0
self.bank_money = 0

def __repr__(self):
return 'Player total: {0} | Bank total: {1}'.format(self.player_money,
self.bank_money)

def toss_coin(self):
toss = random.randint(0, 1)
if toss == 0:
self.turn += 1
self.coin = 'Tails'
return True
else:
self.coin = 'Heads'
return False
def main():
while True:
try:
fee = int(input('Entrance fee: '))
except ValueError:
print('Only positive integers please!')
continue
if fee < 0:
print('Only positive integers please!')
continue
else:
break

game = Game(fee)

while input('Try your luck (y / n)? ') == 'y':


game.turn = 0

print('Coin toss results:\n')


while game.toss_coin():
print(game.coin)

player_win = 2**game.turn
bank_win = fee - 2**game.turn
game.player_money += player_win - fee
game.bank_money += bank_win

print('Heads\n\nNumber of Tails coins: {0}'.format(game.turn))


print('You win: {0} | Bank wins: {1}'.format(player_win, bank_win))
print(game)

if __name__ == '__main__':
main()

Problem condition:
This morning the CIA faxed UTM the following map scan(image is also in the zip file from the email). The total
captured surface is around 42 square miles (duh... this imperial metric). With red is marked the land that is mined by
the guerrilla forces and at the moment they need to evaluate the logistics required to defuse the deadly mines. But they
do not have enough computing resources to compute the red area from the map. Which is why they are playing their
trump card, the brilliant engineers from FAF. The stakes are very high, and lots of innocent lives can be spared. So
please compute the mined area a.s.a.p., using Monte Carlo method. Tip: The recommended python library for image
processing is pillow (not the one you use to sleep).

Monte Carlo methods may be thought of as a collection of computational techniques for the (usually approximate)
solution of mathematical problems, which make fundamental use of random samples. Two classes of statistical
problems are most commonly addressed within this framework: integration and optimization. This article concentrates
on the former: it is the (approximate) calculation of integrals using collections of random samples that people usually
think of when they refer to the Monte Carlo Method. Monte Carlo methodology is also widely used in the simulation
of physical, chemical and biological systems.

Counted number of pixel for red color, so the mined area would be the number of red pixels multiplied by the total
area of the captured surface divided by the total number of pixels.
import cv2
import numpy as np
import math

img = cv2.imread("danger_zone.png")

red_min = np.array([0, 0, 255], np.uint8)


red_max = np.array([0, 0, 255], np.uint8)

dst = cv2.inRange(img, red_min, red_max)


red = cv2.countNonZero(dst)
image_pixel = img.size
mined_area = red * 42 / (img.shape[0] * img.shape[1])

def round_up(n, decimals=0):


multiplier = 10 ** decimals
return math.ceil(n * multiplier) / multiplier

print('The mined area: ' + str(round_up((mined_area), 4)) + ' square miles')

You might also like