Skip to content

Instantly share code, notes, and snippets.

@ExplodingCabbage
Last active January 5, 2020 19:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ExplodingCabbage/15967bdfaad2d4a53c9e4810180245cc to your computer and use it in GitHub Desktop.
Save ExplodingCabbage/15967bdfaad2d4a53c9e4810180245cc to your computer and use it in GitHub Desktop.
Monty Hall Problem Monte Carlo simulation
# A simulation to settle a Twitter argument:
# https://twitter.com/brenorb/status/1213898659752038400
import random
random.seed(42) # For reproducible results
# We have four possible scenarios we can simulate, based on these two bools.
# The first determines whether it's permissible for the host to reveal the car
# on the first door-opening. The second determines whether the contestant is
# using an "always swap" strategy or an "always stick" strategy.
CAN_REVEAL_CAR_EARLY = True
ALWAYS_SWAP = True # if False, always stick
# Let's just have three doors, as in the classic version of the problem:
DOORS = ['A', 'B', 'C']
wins = 0
losses_on_first_reveal = 0 # (Only possible if car can be revealed early)
losses_on_final_reveal = 0
for _ in range(1000):
# Location of the car:
car = random.choice(DOORS)
# We could just as well go for a hard-coded choice here, but let's have the
# contestant choose an initial door randomly:
contestant_choice = random.choice(DOORS)
if CAN_REVEAL_CAR_EARLY:
# The host randomly chooses a door out of the two the contestant didn't
# pick and opens it, potentially revealing the car.
host_choice = random.choice([
door for door in DOORS
if door != contestant_choice
])
if host_choice == car:
# The car was revealed early. The contestant loses immediately.
losses_on_first_reveal += 1
continue
else:
# The host "randomly" chooses a door out of the set of either one or
# two doors that are neither the contestant's choice nor the door
# hiding the car. (Scare quotes since this may only leave one choice!)
host_choice = random.choice([
door for door in DOORS
if door != contestant_choice and door != car
])
remaining_door = next(door for door in DOORS
if door not in (host_choice, contestant_choice))
if ALWAYS_SWAP:
contestant_choice = remaining_door
if contestant_choice == car:
wins += 1
else:
losses_on_final_reveal += 1
print("RULES: the host",
("CAN" if CAN_REVEAL_CAR_EARLY else "CANNOT"),
"reveal the car when they first open a door.")
print("STRATEGY: the contestant will always",
("SWAP" if ALWAYS_SWAP else "STICK"))
print("Wins:", wins)
print("Early losses (before contestant gets a chance to swap):",
losses_on_first_reveal)
print("Losses after the contestant chooses whether to swap:",
losses_on_final_reveal)
# Results observed for each of the four possible scenarios:
# RULES: the host CANNOT reveal the car when they first open a door.
# STRATEGY: the contestant will always SWAP
# Wins: 661
# Early losses (before contestant gets a chance to swap): 0
# Losses after the contestant chooses whether to swap: 339
# RULES: the host CANNOT reveal the car when they first open a door.
# STRATEGY: the contestant will always STICK
# Wins: 339
# Early losses (before contestant gets a chance to swap): 0
# Losses after the contestant chooses whether to swap: 661
# RULES: the host CAN reveal the car when they first open a door.
# STRATEGY: the contestant will always SWAP
# Wins: 333
# Early losses (before contestant gets a chance to swap): 328
# Losses after the contestant chooses whether to swap: 339
# RULES: the host CAN reveal the car when they first open a door.
# STRATEGY: the contestant will always STICK
# Wins: 339
# Early losses (before contestant gets a chance to swap): 328
# Losses after the contestant chooses whether to swap: 333
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment