Using Python to solve the Monty Hall problem

May 13, 2022 ยท 3 min read
post

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'
))

png

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'
))

png

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 ๐Ÿ™‚

Maxime Borry, PhD.
Authors
Maxime Borry, PhD.

I am Maxime, a Bioinformatics scientist specializing in the development of statistical tools and workflows for the analysis of omics data. I have extensive experience working with prokaryotic, eukaryotic, and human systems, and I excel at transforming complex biological datasets into scientific results through rigorous approaches and scalable bioinformatics solutions.

After an undergraduate degree in biology, I initially pursued studies in population and environmental sciences. After realizing I wanted to focus more on statistics and data analysis, I returned to complete an M.Sc. in Bioinformatics.

I completed my PhD in the Microbiome Sciences research group at the MPI-EVA, studying ancient DNA metagenomics, and continued this work as a postdoctoral researcher at the Leibniz-HKI with a focus on fermentation microbiomes. Recently, I transitioned to computational oncology and cancer research, focusing on personalized cancer vaccine development and the analysis of cancer genomics datasets.