The problem is posed as follows:
You are 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 Door 1, and the host, who knows what's behind the doors, opens Door 3, which has a goat. The host then says, “Do you want to stay with your original door or switch to Door 2?” Is it to your advantage to switch your choice? — Wikipedia
Without delving too deep, it is always in your best interest to switch to doors rather than stay with your initial choice. On average, your chances of winning the car is 66.67% if you switch doors compared to 33.33% if you remain with your initial choice. The easiest way to explain this solution is by using the image below:
Initially, you have a 33.33% chance of choosing the door with the car behind it. However, when the host opens Door 3, the chance the car is behind Door 3 goes down to 0%, but the chance it is behind Door 2 goes up to 66.67%. With that information, it is in your best interest to switch to Door 2.
However, we can use Python to simulate 100,000 games to solve this problem. The program records whether the car is behind the selected door or the other unopened door for each game. The simulation then outputs the average chance of winning the car if you always stayed with your selection versus consistently switching doors.
The code below requires the use of the NumPy library. I used the time module to track the time it took to run the simulations. It took less than 3 seconds to run 100,000 iterations of the Monty Hall problem on my PC.
from numpy import random
import numpy as np
import time
def MontyHallSimulation (N):
ChoiceUnchanged=[]
ChoiceChanged=[]
NN=1
for i in range(0,N):
# 1) The car is placed behind a random door.
WinningDoor=random.choice(['Door 1', 'Door 2', 'Door 3'])
# 2) The contestant selects a random door.
FirstSelection=random.choice(['Door 1', 'Door 2', 'Door 3'])
# 3) The host opens a door that is different than the contestants choice
# and not the door with the car.
HostOpens=list(set(['Door 1', 'Door 2', 'Door 3'])-set([FirstSelection,WinningDoor]))[0]
# 4) The other door is not the participant's selected door and not the opened door.
OtherDoor=list(set(['Door 1', 'Door 2', 'Door 3'])-set([FirstSelection,HostOpens]))[0]
# 5) Add "True" to a list where the participant DOES NOT change their selection AND thier
# selection identified the door with the car.
ChoiceUnchanged.append(FirstSelection==WinningDoor)
# 6) Add "True" to a list where the participant DOES change their selection and thier
# new selected door has the car behind it.
ChoiceChanged.append(OtherDoor==WinningDoor)
# NOTE: The boolean object "TRUE" is equal to 1 and "False" is equal to 0.
# As such, we can use the "sum" function to get the total number of wins
# for each strategy.
print(f'\n\
{N:,} games were played \n\
Chances of winning the car based on the following strategies:\n\
Remaining with initial selection: {"{:.1%}".format(sum(ChoiceUnchanged)/N)}\n\
Switching doors: {"{:.1%}".format(sum(ChoiceChanged)/N)}')
###############################
###### Run the Simulation######
###############################
Start_time = time.time()
MontyHallSimulation(N=100000)
print(f'\nSimulation Completed in: {round(time.time()-Start_time,2)} Seconds')
Conclusion
The above Python code is a quick way to solve the Monty Hall problem. If you have another puzzle, you'd like to see programmed using Python, leave a comment. You can extend this problem to situations where the game show can switch the prize position, say 33.33% of the time after opening a door.