# Using Python to solve the Monty Hall problem

Is it better to change ?

I’ve been recently reminded of the Monty Hall problem, and I thought I would try to show how to solve it with simulations in Python.

Inspired from the 60’s American TV game show Let’s Make a Deal, the principle is the following: The player is faced with three doors, behind one of which is a big prize (a 🚗), and behind the two others, a 🐐, and has to choose one, without opening it yet.

After the participant chose a door, Monty Hall (the host of the show) opens one of the two other door, behind which is always a 🐐.*What is the best strategy to win the 🚗 ?*

Keeping the original choice, or changing of door ?

It turns out that…

Read further to find out 😉

```
import numpy as np
import altair as alt
import pandas as pd
alt.renderers.enable('mimetype')
```

```
nb_games = 10000 # The number of games we're going to simulate
```

```
games = []
for i in range(nb_games):
game = np.repeat('🐐', 3)
prize = np.random.randint(0,3,1) # the door behind which the car is hidden
game[prize]='🚗'
games.append(game)
```

### Strategy: keep door

```
wins=0 # win counter
for i in range(nb_games):
doors = [0,1,2]
player_door_choice = int(np.random.choice(doors, 1)) # the player initial's door choice
doors.remove(player_door_choice) # doors not chosen by player
for j in doors: # Monty Hall reveals that behind one of the door not chosen is a goat
if games[i][j] == '🐐':
goat_door = j
if games[i][player_door_choice] == '🚗': # The player keeps his initial door choice
wins += 1
```

```
print(f"Winning percentage: {round(wins/nb_games*100,1)}%")
```

```
Winning percentage: 32.1%
```

```
x = ['🚗','🐐']
y = [round(wins/nb_games*100, 0), 100 - round(wins/nb_games*100, 0)]
source = pd.DataFrame({'x':x, 'y':y})
(alt.Chart(source).mark_bar(size=30).encode(
x=alt.X('x', axis=alt.Axis(title=None)),
y=alt.Y('y', axis=alt.Axis(title='outcome %'))
).properties(width=200, title='Strategy: keep same door')
.configure_axis(labelFontSize=20)
.configure_title(
fontSize=20,
font='Courier',
anchor='start',
color='gray'
))
```

### Strategy: change door

```
wins=0
for i in range(nb_games):
doors = [0,1,2]
player_door_choice = int(np.random.choice(doors, 1)) # the player initial's door choice
doors.remove(player_door_choice) # doors not chosen
for j in doors: # Monty Hall reveals that behind one of the door not chosen is a goat
if games[i][j] == '🐐':
goat_door = j
doors.remove(goat_door) # the player changes its door choice
if games[i][doors[0]] == '🚗':
wins += 1
```

```
print(f"Winning percentage: {round(wins/nb_games*100,1)}%")
```

```
Winning percentage: 66.7%
```

```
x = ['🚗','🐐']
y = [int(wins/nb_games*100), 100 - int(wins/nb_games*100)]
source = pd.DataFrame({'x':x, 'y':y})
(alt.Chart(source).mark_bar(size=30).encode(
x=alt.X('x', axis=alt.Axis(title=None)),
y=alt.Y('y', axis=alt.Axis(title='outcome %'))
).properties(width=200, title='Strategy: change door')
.configure_axis(labelFontSize=20)
.configure_title(
fontSize=20,
font='Courier',
anchor='start',
color='gray'
))
```

As I showed above, the **door changing strategy is much better** with a 66.6% change of winning, vs 33.3% if we keep the original door.

If you want to learn more about the Monty Hall problem, and how to prove using the Baye’s theorem, have a reat at the wikipedia page

Finally, the code behind this post is here

Last but not least, if you want to make it interactive with JavaScript P5, please have a look at this video from the Coding Train, which inspired this blog post 🙂