CoCalc Public FilesNew Projects and Problems / Monty Hall.ipynb
Author: Peter Francis

# Monty Hall Simulation

In [2]:
import random as rd

In [3]:
def run(V = False):
# create door scheme
doors = [False, False, False]
# place car
car = rd.randint(0,2)
doors[car] = True
if V: print(f'doors are {doors}')
# contestant chooses door
firstChoice = rd.randint(0,2)
if V: print(f'contestant chooses {firstChoice}')
# monty chooses a door to open
possibleToReveal = [door for door in [0,1,2] if door not in [car, firstChoice]]
montyOpens = possibleToReveal[rd.randint(0,len(possibleToReveal)-1)]
if V: print(f'monty opens {montyOpens}')
# contestant chooses to switch or stay
movement = ['switch', 'stay'][rd.randint(0,1)]
if V: print('contestant chooses to ' + movement + ' so is at ', end='')
# contestant gets the new location
possibleToSwitchTo = [door for door in [0,1,2] if door not in [montyOpens, firstChoice]][0]
finalChoice = {'switch': possibleToSwitchTo, 'stay':firstChoice}[movement]
if V: print(f'{finalChoice}')
# contestant gets their prize
prize = doors[finalChoice]
if V:
if prize:
print('contestant wins')
else:
print('contestant loses')
return (movement, prize)

In [4]:
run('V')

doors are [False, True, False] contestant chooses 0 monty opens 2 contestant chooses to switch so is at 1 contestant wins
('switch', True)
In [5]:
def run2(V = False):
# create door scheme
doors = [False, False, False]
# place car
car = rd.randint(0,2)
doors[car] = True
if V: print(f'doors are {doors}')
# contestant chooses door
firstChoice = rd.randint(0,2)
if V: print(f'contestant chooses {firstChoice}')
# monty chooses a door to open
montysChoice = rd.randint(0,2)
while montysChoice == firstChoice and montysChoice == car:
montysChoice = rd.randint(0,2)
montyOpens = montysChoice
if V: print(f'monty opens {montyOpens}')
# contestant chooses to switch or stay
movement = ['switch', 'stay'][rd.randint(0,1)]
if V: print('contestant chooses to ' + movement + ' so is at ', end='')
# contestant gets the new location
possibleToSwitchTo = [door for door in [0,1,2] if door not in [montyOpens, firstChoice]][0]
finalChoice = {'switch': possibleToSwitchTo, 'stay':firstChoice}[movement]
if V: print(f'{finalChoice}')
# contestant gets their prize
prize = doors[finalChoice]
if V:
if prize:
print('contestant wins')
else:
print('contestant loses')
return (movement, prize)

In [12]:
def simulate(f, n):
wonWhenSwitched = 0
lostWhenSwitched = 0
wonWhenStayed = 0
lostWhenStayed = 0
for _ in range(n):
movement, prize = f()
if movement == 'switch':
if prize == 1:
wonWhenSwitched += 1
else:
lostWhenSwitched += 1
elif movement == 'stay':
if prize == 1:
wonWhenStayed += 1
else:
lostWhenStayed += 1
print(f'Switch and win:  {round(wonWhenSwitched*100/(wonWhenSwitched+lostWhenSwitched), 3)} %')
print(f'Switch and lose: {round(lostWhenSwitched*100/(wonWhenSwitched+lostWhenSwitched), 3)} %\n')
print(f'Stay   and win:  {round(wonWhenStayed*100/(wonWhenStayed + lostWhenStayed), 3)} %')
print(f'Stay   and lose: {round(lostWhenStayed*100/(wonWhenStayed + lostWhenStayed), 3)} %')

In [15]:
# where monty knows where the car is

simulate(run,1_000_000)

Switch and win: 66.662 % Switch and lose: 33.338 % Stay and win: 33.36 % Stay and lose: 66.64 %
In [16]:
# where monty doesn't know where the car is

simulate(run2,1_000_000)

Switch and win: 33.285 % Switch and lose: 66.715 % Stay and win: 33.452 % Stay and lose: 66.548 %
In [ ]: