The famous Monty Hall brain teaser:
Suppose you're on a game show, and you're given the choice of three doors: Behind one door is a car; behind the others, goats. You pick a door, say No. 1, and the host, who knows what's behind the doors, opens another door, say No. 3, which has a goat. He then says to you, "Do you want to pick door No. 2?" Is it to your advantage to switch your choice?
There is a really fun discussion over at Marilyn vos Savant's site.
Ok, now to setup the problem, along with some kind of visuals and what not.
In [293]:
import random
import numpy as np
# for plots, cause visuals
%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sns
In [279]:
def switch_door(guess, goat_door_opened):
"""takes in the guessed door and the goat door opened
and returns the switched door number"""
doors = [0,1,2]
doors.remove(goat_door_opened)
doors.remove(guess)
return doors[0]
Now the actual monty hall function - it takes in a guess and whether you want to switch your guess, and returns True or False depending on whether you win
In [280]:
def monty_hall(guess=0, switch_guess=False, open_goat_door=True):
"""sets up 3 doors 0-2, one which has a pize, and 2 have goats.
takes in the door number guessed by the player and whether he/she switched door
after one goat door is revealed"""
doors = [door for door in range(3)]
np.random.shuffle(doors)
prize_door = doors.pop()
goat_door_opened = doors[0]
if goat_door_opened == guess:
goat_door_opened = doors[1]
if switch_guess:
return switch_door(guess, goat_door_opened) == prize_door
else:
return guess == prize_door
Now to run through a bunch of monty hall games:
In [281]:
no_switch = np.mean([monty_hall(random.randint(0,2), False) for _ in range(100000)])
no_switch
Out[281]:
Not switching doors wins a third of the time, which makes intuitive sense, since we are choosing one door out of three.
In [282]:
yes_switch = np.mean([monty_hall(random.randint(0,2), True) for _ in range(100000)])
yes_switch
Out[282]:
This is the suprising result, since switching our guess increases the win rate to two third! To put it more graphically:
In [284]:
plt.pie([yes_switch, no_switch], labels=["Switching win %", "Not switching win %"],
autopct='%1.1f%%', explode=(0, 0.05));
So our chances of winning essentially double if we switch our guess once a goat door has been opened.
A good monty hall infographic:
In [294]:
def switch_door_no_revel(guess):
"""takes in the guessed door
and returns the switched door number"""
doors = [0,1,2]
doors.remove(guess)
np.random.shuffle(doors)
return doors[0]
Then I removed the revealing the goat door code from the original monty hall function above:
In [295]:
def monty_hall_no_reveal(guess=0, switch_guess=False):
"""sets up 3 doors 0-2, one which has a pize, and 2 have goats.
takes in the door number guessed by the player and whether he/she switched door
"""
doors = [door for door in range(3)]
np.random.shuffle(doors)
prize_door = doors.pop()
if switch_guess:
return switch_door_no_revel(guess) == prize_door
else:
return guess == prize_door
Now to run some sims:
In [296]:
no_switch_no_reveal = np.mean([monty_hall_no_reveal(random.randint(0,2), False) for _ in range(100000)])
yes_switch_no_reveal = np.mean([monty_hall_no_reveal(random.randint(0,2), True) for _ in range(100000)])
In [297]:
plt.bar([0,1], [yes_switch_no_reveal, no_switch_no_reveal], tick_label=["Switched Guess","Didn't Switch"],
color=["blue","red"], alpha=0.7);
There is no impact of switching our guess if a goat door hasn't been revealed. Which makes sense to, since whatever door we choose, it has 1/3 probablity of winning.
In [ ]: