# Monty Hall Problem Simulation in Python

Monty Hall problem is an interesting statistical problem. It first appeared in 1975 and the original version of this question is following1:

"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?"

You might guess the chance for winning is 1/2. All in all, there are 3 doors, you pick one, host opens second door which—as he knows—hides goat. So there are two doors left, one hides goat, other one prize. You now have to decide whether to keep your original choice, or switch doors which you want to open.

Problem is, this would be only correct if the host would not know which doors wins. In that case, he would open single doors by random with probability of 1/3 that he wins (and not you). If he opens a doors with goat, you then have a chance to win of 1/2. It would not matter then which doors you pick.

But because the host knows, situation is different. You first pick one door (call them A) from all three. Your chances for winning are now 1/3. Two doors are left (B and C) and the probability that prize is behind one of these two remaining doors is 2/3. Host will then open one door, either B or C, that hide goat (this means they are not winning). So lets say that host will now open door B which reveal a goat.

And now is the catch. Probability that prize is behind door A is 1/3 all the time. Probability that prize is behind doors B or C (together) is 2/3. But door B is now opened and you can clearly see a goat behind them. So the probability that prize is behind door B is now 0. This means that prize is behind door C with probability of 2/3. Don't trust me and see for yourself below.

First, there is a table showing all possible states (blatantly copied from Wikipedia1).

Door "A"Door "B"Door "C"Result if you stay on door "A"Result if you switch doors
GoatGoatPrizeLossWin
GoatPrizeGoatLossWin
PrizeGoatPrizeWinLoss

Table above might be enough but pictures are better. I have decided to create a computer simulation in Python to really test this problem.

The program first initiates many rounds (each consisting of 3 doors) with randomly chosen prize position. There are 3 functions for 3 different situations: player keeps his initial choice, player randomly decides whether to keep or switch his choice, and the last one, player switches his answer everytime. Program will run 1000 iterations.

We will first generate multiple random game rounds.

def generate_game(n: int):
game = []

for _ in range(n):
doors = [False] * 3
prize_pos = randint(0, 2)
doors[prize_pos] = True
game.append(doors)

return game


Then create simple helper function to reveal single door with goat. To make this simulation more straightforward we will shuffle only the position of prize. Computer will then pick Door 1 everytime. So the "host" will have to decide only between Door 2 or 3.

def reveal_goat(doors):
for i in range(1, 3):
if doors[i] == False:
return i


Now lets simulate random choice. In this case, computer will pick Door 1, host will then reveal Door 2 or Door 3 depending on which one contains goat. Computer will then randomly decide whether to keep his initial choice or switch.

def simulate_random_choice(game: list):
wins = 0
attempts = 0

history = []

for doors in game:
attempts += 1

# Host reveals a door with goat.
goat = reveal_goat(doors)

# Player randomly chooses whether
# to keep initial choice or switch.
new_choice = randint(0, 1)

# Keep initial choice if new_choice is 0.
# Switch to next door if new_choice is 1.
final_choice = 0 if new_choice == 0 else 2 if goat == 1 else 1

if (doors[final_choice] == True):
wins += 1

history.append(wins / attempts)

return wins, history


Simulation of keeping initial choice is easier.

def simulate_keep_choice(game: list):
wins = 0
attempts = 0
history = []

for doors in game:
attempts += 1

# User does not switch game.
if (doors[0] == True):
wins += 1

history.append(wins / attempts)

return wins, history


In last simulation, computer will always switch to the remaining door.

def simulate_switch_choice(game: list):
wins = 0
attempts = 0
history = []

for doors in game:
attempts += 1

# Host reveals a door with goat.
goat = reveal_goat(doors)

# Player switches his doors
# (here he chooses the non-opened doors).
new_choice = 1 if goat == 2 else 2

if (doors[new_choice] == True):
wins += 1

history.append(wins / attempts)

return wins, history


You can view the full Python source code in my GitHub gist or see an exported Jupyter Notebook page. It contains full source code including the graphing function which was not including in this post.