After John W’s skepticism, I decided to put my code where my mouth is — please see:
/portfolio/montyhallsimulator/
It has a simulator, demonstrating the superiority of switching, based on a sample size of 10,000 or less. Source code included. Check it out!
For those of you who remember Let’s Make a Deal the idea of the threedoor choice is very familiar. For those who aren’t familiar with Monty Hall and his extravaganza of gameshowness, here’s the lowdown:
Door 1

Door 2

Door 3

Goat

Goat

New Car

The contestant is presented with a choice of three doors. Two of them have a goat, and one of them has a fabulous prize, like a new car, or a boat, or an evening with Brad Pitt, or whatever. (the contestants were mostly women, since at the time less women were in the workforce, therefore they were the target demographic). Anyways, here’s how it works. They pick one of the doors, then Monty reveals one of the two doors they did not choose; but the door revealed will always contain a goat. The contestant is then allowed to stick with their choice, or change it. The puzzle here is: Is it better odds, statistically speaking, to stick with your choice, or change it, after the goat is revealed? Most mathematicians have said yes in the past, but Marilyn Vos Savant disagreed. Here is a paraphrasing of her proof:
The contestant can pick any one of the three doors, so the odds are 1:3 she will choose correctly. For example, she’ll choose #2. 


Now the host will reveal which one of the doors contains a Goat. It is a certainty he will reveal a goat behind that door, as opposed to accidentally revealing the prize. 


So the odds of Door 1 in this case of being the correct door are 0:3. The odds of your door are 1:3. 


This means that the odds of the remaining door are 2:3 it will be correct. So switching will yield the prize 66% of the time rather than just 33% of the time. 



Scenarios
I’ll now illustrate two different examples of possible outcomes. The left column will be assuming that the contestant always changes their choice when offered, and the right column will be assuming the contestant never changes.
Read each set of data from top to bottom. The sets illustrate the change in gamestate as the game progresses. The lightened boldfaced cell is the selection by the contestant.
Instance 1
Always Switch

 
Never Switch


Door 1

Door 2

Door 3

 
Door 1

Door 2

Door 3


Goat

Car

Goat

 
Goat

Car

Goat


(selected)    (selected)  
Goat

Car

Goat

 
Goat

Car

Goat


(revealed)    (revealed)  
Goat

Car

Goat

   
Goat

Car

Goat


(changed)  (not changed )  
Outcome: Win (changed to Car)  Outcome: Loss (stayed with goat) 
Instance 2
Always Switch

 
Never Switch


Door 1

Door 2

Door 3

 
Door 1

Door 2

Door 3


Goat

Car

Goat

 
Goat

Car

Goat


(selected)    (selected)  
Goat

Car

Goat

 
Goat

Car

Goat


revealed    revealed  
Goat

Car

Goat

   
Goat

Car

Goat


(changed)  (not changed )  
Outcome: Loss (changed to Goat)  Outcome: Win (stayed with car) 
Instance 3
Always Switch

 
Never Switch


Door 1

Door 2

Door 3

 
Door 1

Door 2

Door 3


Goat

Car

Goat

 
Goat

Car

Goat


(selected)    (selected)  
Goat

Car

Goat

 
Goat

Car

Goat


(revealed)    (revealed)  
Goat

Car

Goat

   
Goat

Car

Goat


(changed)  (not changed)  
Outcome: Win (changed to Car)  Outcome: Loss (stayed with goat) 
Do you see the reasoning why changing is always better? Two out of three situations where you change your doorchoice end you up with the car, whereas only 1 in three wins you the car if you don’t change your choice.
Changing your decision effectively inverses the odds into your favor. The fact that the door revealed is not a random door, but rather one of the remaining GOAT DOORS is very important to this; if it weren’t for that, this strategy would not work.
Source Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 
<?php $n = isset($_GET['n']) && preg_match("/^\d+$/", $_GET['n']) ? $_GET['n'] : "10"; // Be nice to my host  let's keep the sample sizes relatively small. if ($n > 10000) exit(); /* the_full_monty()  runs through iterations of a monty_hall scenario. argument $switch determines whether it should always switch (true) or never switch (false) */ function the_full_monty($samplesize, $switch = true) { } define('CAR', 1); define('GOAT', 0); class MontyHallSim { private $iterations = 10; // Total private $no_switch_wins = 0; // Number of wins private $switch_wins = 0; private $doors = array(3); private $selection = 0; private $new_selection = 1; private $revealed = 0; public function __construct($iterations){ $this>iterations = $iterations; } public function run() { $this>no_switch_wins = 0; $this>switch_wins = 0; for ($i = 0; $i < $this>iterations; $i++) { $this>doors = array(GOAT, GOAT, GOAT); // Reset doors to all goats $this>doors[rand(0,2)] = CAR; // Replace one of them with a car $this>selection = rand(0,2); // Contestant chooses a door // Reveal one of the goats $this>revealed = 1; do { $this>revealed++; } while ($this>doors[$this>revealed] == 1  $this>revealed == $this>selection); // If set to alwaysswitch, then switch choices. /* The bitwise operator works because: Sel Rev Sum ~Sum 0 (00) 1 (01) 1 (01) 2 (10) 0 (00) 2 (10) 2 (10) 1 (01) 1 (01) 2 (10) 3 (11) 0 (00) */ $this>new_selection = ($this>selection + $this>revealed) ^ 3; if ($this>doors[$this>new_selection] == CAR) { $this>switch_wins++; } if ($this>doors[$this>selection] == CAR) $this>no_switch_wins++; } // endfor } public function graph() { } public function stats() { ?> <div id="data"><ul> <?php echo "<li>Total number of wins where switching helped: " . $this>switch_wins . ", " . 100*($this>switch_wins / $this>iterations) . "%</li>"; echo "<li>Total number of wins where switching hurt: " . $this>no_switch_wins . ", " . 100 * ($this>no_switch_wins / $this>iterations) . "%</li>"; ?> </div> <?php } } ?> 
JOhn W.
Given that we’ll always make one choice in 3, and that the selection will always be dropped to 2…. we may be able to discount the entire first step.
The initial selection only determines which of the 2 goats we see next.
Since this first choice never changes that fact, can’t we discount it, and then get to the second choice, which is always 5050 stab?
I’d love to see your logic applied to a random assignment, (initial) of the 3, the informal display of bleetWell #1, and then the final selection.
I postulate that the initial selection is irrelevant and only serves to show one goat or the other. There seems to be no effect on the outcome, which (being a selection of 2) is 50/50.
Monty Hall and his pals rev up the crowd with uncertainty for sure.
I will accept the challenge to combine this game and the background switcher to see how often my background shows a goat!
JW
# DIsregard the noise #
BTW – Goats smell funny and have disturbing eyes.
Aaron
They key importance of the first step is that it reduces the probabilty of selecting a goat from 2:3 to 1:2 (and simultaneously increases the probability of selecting the prize from 1:3 to 1:2)
If you were simply randomly revealing one of the doors, then it would be less important. Read through all the sample outcomes at the end of the blog post here — the left column is “always switch” and the right column is “never switch”.
Of all possible configurations, the “always switch” has a 2:3 chance of winning, whereas never switch has a 1:3 chance of winning. You double your chances by switching.
Write up a simple script that runs through N loops of this process and calculates the outcomes. Something like this:
declare doors[3], initialized to {0,0,0}
declare selection, initialized to 0
declare new_selection, initialized to 0
declare revealed, initialized to 0
declare wins, total_runs, initialized to 0
while total_runs is less than “N” argument:
randomly assign “1” to one of the doors
randomly assign a value between 1 and 3 to selection
iterate through doors[], set revealed to first index where the value is 0 and where the index does not equal the selection
# This is for always switch version.
# To change to noswitch, simply skip this step
iterate through doors[], set new_selection to the first index that is not the selection OR revealed values
if doors[new_selection] is “1”, then increment wins
increment total_runs
endwhile;
For a sufficiently large enough value of “N” (10,000 – 100,000 should probably be enough), wins/total_runs should approximately be 66% for the alwaysswitch version. The noswitch version should approximate 33%.
I’ll see if I can write it up in PHP.
JOhn W.
Aaron.
Wow all this work to prove it out… Geeky goodness!
at first selection, there are 3 choices. One you pick has 33 pct chance of winning. That won’t change.
The two you don’t pick have 66 chance of containing the winning prize.
Lets say one of the remaining two is not removed, but rather attached to the other, we still have a 66 pct chance of winning if we pick the other 2.
So.. sticking with first pick is still 33 pct, but picking the other 2 is 66 pct.
That seems a lot more intuitive!!!
I will savor this one.. it will pop up again in life. Maybe on a game show!
JW