In [1]:
def monty_monte(doors, goats, reveals, trials):
import random
random.seed()
assert goats > 1, "There must be at least two goats"
assert doors > 2, "There must be at least three doors"
assert doors - goats > 0, "There must be at least one car"
assert goats - reveals > 0, "There must be more goats than reveals"
won_if_stick, won_if_switch = 0, 0
for trial in range(trials):
prize_list = []
for i in range(goats): prize_list.append('goat')
for i in range(doors - goats): prize_list.append('car')
# randomize list in place instead of picking members at random; it amounts to the
# same thing, but the manipulations are easier
random.shuffle(prize_list)
# first you pick a random door (# 1, index 0, since the list order is now random)
# if it's a car, count it as a win if you stick (don't change your selection)
# either way, take it out of the list, it's no longer in play
if prize_list[0] == 'car': won_if_stick += 1
del prize_list[0]
# now Monty must reveal one (or possibly more) goat(s).
# we iterate through the list until we find one, then delete it.
# we repeat this the number of times specified in the reveals variable
for reveal in range(reveals):
monty_choice = 0
while prize_list[monty_choice] != 'goat':
monty_choice += 1
del prize_list[monty_choice]
# now you switch your choice to the first item in the list.
# Remember, we randomized the order earlier, so it's the same as choosing an item at random.
if prize_list[0] == 'car': won_if_switch += 1
print("Probability of winning if you stick: {0}".format((won_if_stick*1.0/trials)))
print("Probability of winning if you switch: {0}".format(won_if_switch*1.0/trials))
print("Fold improvement: {0}".format(round(won_if_switch*1.0/won_if_stick,3)))
monty_monte(3,2,1,1000)
In [2]:
monty_monte(3,2,1,100000) # the classic variant
In [3]:
monty_monte(100,99,1,10000) # often cited when trying to explain the Monty Hall problem
In [4]:
monty_monte(6,4,2,10000) # six doors, four goats, two reveals, why not?
In [ ]: