This repository has been archived by the owner on Jun 10, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmontyhall.py
140 lines (108 loc) · 3.98 KB
/
montyhall.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!/usr/bin/env python
# libs
import random
# classes
class MontyHall(object):
"""A class with various methods for simulating the Monty Hall problem."""
def lmad(self):
"""Interactive version of Monty Hall problem (i.e. Lets Make A Deal)."""
# start game
print('Let\'s Make A Deal')
try:
# how many doors
ndoors = int(input('How many doors: '))
# which door would you like
first_choice = int(input('Choose one door out of {}: '.format(ndoors)))
# now the host calculates
results = self.simulate(ndoors, first_choice)
# would you like to switch
switch = input('Would you like to switch doors [y/n]: ')
# converst switch to true/false
switch = True if switch in {'y', 'Y', 'yes', 'Yes', 'YES'} else False
# check switch
final_choice = results['second_choice'] if switch else first_choice
# prepare results
results['final_choice'] = final_choice
# return results
return results
except EOFError or KeyboardInterrupt:
# do nothing but end silently
pass
@staticmethod
def predict(ndoors):
"""Calculate the predicted probabilities of no switch vs. switch.
Args:
ndoors (int): The number of doors to use.
Returns:
ndoors (int): The number of doors used.
noswitch (float): Probability of winning if players does not switch.
switch (float): Probability of winning if player switches.
"""
# calculate probabilities
no_switch = 1.0 / float(ndoors)
switch = 1.0 - no_switch
# return results dictionary
return {
'ndoors': ndoors,
'noswitch': no_switch,
'switch': switch
}
@staticmethod
def simulate(ndoors, first_choice):
"""Non-interactive version of Monty Hall problem.
Args:
ndoors (int): The number of doors to use.
first_choice (int): The first door the player chooses.
Returns:
first_choice (int): The first door the player chooses.
second_choice (int): The second door the player can switch to.
car (int): The door hiding the car.
"""
# get random number in range of ndoors (representing the car to be won)
car = random.randint(1, ndoors)
# get second_choice (i.e. 2nd door to choose from)
if first_choice != car:
second_choice = car
else:
while True:
second_choice = random.randint(1, ndoors)
if second_choice != car:
break
# return results
return {
'first_choice': first_choice,
'second_choice': second_choice,
'car': car
}
def experiment(self, ndoors, first_choice, ngames):
"""Run multiple games of Monty Hall problem.
Args:
ndoors (int): The number of doors to use.
first_choice (int): The first door the player chooses.
ngames (int): The number of games to run.
Returns:
noswitch (float): Experimental percent of winning without switching.
switch (float): Experimental percent of winning with switching.
"""
# setup initial values
switch, noswitch = 0, 0
# setup loop
for _ in range(ngames):
# get results of game
game = self.simulate(ndoors, first_choice)
# update statistics
if game['first_choice'] == game['car']:
noswitch += 1.0
else:
switch += 1.0
# calculate results
return {
'noswitch': noswitch / (switch + noswitch),
'switch': switch / (switch + noswitch)
}
# executable only
if __name__ == '__main__':
# libs
import fire
# bang bang
fire.Fire(MontyHall)