The Monty Hall Monte Carlo simulator, or as I like to call it,

'monty_monte'

By David Taylor, a.k.a. Prooffreader

See an article about the Monty Hall Problem with a nice animated gif at:


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)


Probability of winning if you stick:  0.319
Probability of winning if you switch: 0.681
Fold improvement: 2.135

In [2]:
monty_monte(3,2,1,100000) # the classic variant


Probability of winning if you stick:  0.33303
Probability of winning if you switch: 0.66697
Fold improvement: 2.003

In [3]:
monty_monte(100,99,1,10000) # often cited when trying to explain the Monty Hall problem


Probability of winning if you stick:  0.0092
Probability of winning if you switch: 0.0206
Fold improvement: 2.239

In [4]:
monty_monte(6,4,2,10000) # six doors, four goats, two reveals, why not?


Probability of winning if you stick:  0.3266
Probability of winning if you switch: 0.8036
Fold improvement: 2.461

In [ ]: