You pick one of three doors. The host — who knows what's behind every door — opens a different door to reveal a goat, then offers you the chance to switch. Should you switch or stay?
The near-universal wrong answer is 50/50. The correct answer: switching wins with probability 2/3. Staying wins with probability 1/3. This has been verified analytically, computationally, and empirically millions of times. When Marilyn vos Savant published the correct solution in 1990, she received thousands of letters from PhD mathematicians insisting she was wrong. She was not.
The Case Enumeration
Without loss of generality, assume the car is behind Door 1. There are three equally probable initial picks:
Case 1: You pick Door 1 (car). P = 1/3. Switch → LOSE. Stay → WIN. Case 2: You pick Door 2 (goat). P = 1/3. Switch → WIN. Stay → LOSE. Case 3: You pick Door 3 (goat). P = 1/3. Switch → WIN. Stay → LOSE. Switch wins in 2 of 3 cases → P(win | switch) = 2/3 Stay wins in 1 of 3 cases → P(win | stay) = 1/3
The Bayesian Derivation
Suppose you pick Door 1 and the host opens Door 3. Applying Bayes' Theorem:
P(car at Door 1 | host opens Door 3) = (1/2 × 1/3) / (1/2) = 1/3 P(car at Door 2 | host opens Door 3) = (1 × 1/3) / (1/2) = 2/3
The host's action is not random — he always reveals a goat and never opens your door. That constrained action transfers probability mass from the opened door onto the remaining unchosen door. Switching captures that mass; staying forfeits it.
The Generalized N-Door Result
With N doors, after the host opens N−2 goat doors:
P(win | switch) = (N−1) / N P(win | stay) = 1 / N
At N=1000: switching wins 999/1000 of the time.
Python Simulation (1,000,000 Trials)
import random
def monty_hall_trial(switch=True):
doors = [0, 1, 2]
car = random.choice(doors)
pick = random.choice(doors)
goat_doors = [d for d in doors if d != pick and d != car]
host_opens = random.choice(goat_doors)
if switch:
final = [d for d in doors if d != pick and d != host_opens][0]
else:
final = pick
return final == car
n = 1_000_000
switch_rate = sum(monty_hall_trial(True) for _ in range(n)) / n
stay_rate = sum(monty_hall_trial(False) for _ in range(n)) / n
print(f"Switch: {switch_rate:.4f} (exact: 0.6667)")
print(f"Stay: {stay_rate:.4f} (exact: 0.3333)")
Read the full article with complete Bayesian derivation and N-door generalization →
Top comments (0)