I read a very interesting article on the NY Times today, linked from this /. article, about the Monty Hall Problem. The problem has apparently caused much embarrassment among mathematicians, and now psychologists, and it’s a very interesting read.

I couldn’t quite agree with the argument put forth, and I’m no mathematician, so I wrote a simple program to calculate some numbers for me… first, lets review the problem at hand:

- I present you with three closed doors. Behind one is a new car, the other two, a goat.
- You choose one of the three doors, hoping it has a car.
- I open one door exposing a goat.
- You may keep your original door, or change your mind choosing the other closed door.
- Open your door, if it’s the car, you can keep it.

So as impulsive humans, it’s easy to see, and think, that since I open one door, your final choice gives you a 50/50 shot at winning a car. The argument in the paper those posits that you should change your mind, since your original decision only had a 33% chance of being correct, and a 66% chance of being wrong.

The source for this simulation is included below. It very closely follows the steps I laid out above, resetting the doors at the start of the loop, randomly choosing which one contains a “car” (true value). The simulates a user’s choice (rand mod three), opens a door containing a goat, and then simulates the user randomly choosing to change their mind (rand mod 2). It totals how many times the user kept their original door and won a car, as well as how many times the user changed their minds and won a car.

I present the results here for you to mull over – I ran 75,000,000 iterations of the loop and got the following:

```
How many iterations: 75000000
In 75000000 runs, we won a car 44.4418% of the time.
Used original choice and won a car 12499628 out of 37505245 times... 33.3277%
Chose the other door and won a car 20831722 out of 37494755 times... 55.559%
```

Suggesting that your original choice is only correct 33% of the time – which makes perfect sense. However, after I open a door and narrow your choices down, you have about a 50% chance of winning the car when you change your mind.

Since your original choice was made out of three closed doors, you’ll win with that choice 33% of the time. However, when you change your mind you’re only choosing out of two closed doors, so you’ll win about 50% of the time.

Doesn’t add up, I know – but makes a certain bit of sense.

/** Monty Hall's game simulator… Calculates win percentages when you keep your original door or change your mind in a monty hall problem - http://en.wikipedia.org/wiki/Monty_Hall_problem * Author: Timothy C. Fanelli Date: April 10, 2008 **/ include <cstdlib> include <cassert> include <ctime> include <iostream> using namespace std; int main() { int iterations; bool contents[] = { false, false, false }; cout << "How many iterations: "; cin >> iterations; int changedDoorCount = 0; int correct[] = {0, 0}; srand( time( 0 ) ); for ( int i = 0; i < iterations; ++i ) { int goatOne, goatTwo; int carIdx = rand() % 3;`// Setup the monty hall's doors:`

`contents[0] = false;`

`contents[1] = false;`

`contents[2] = false;`

`contents[carIdx] = true;`

`if ( carIdx == 0 ) {`

`goatOne = 1;`

`goatTwo = 2;`

`}`

`else if ( carIdx == 1 ) {`

`goatOne = 0;`

`goatTwo = 2;`

`}`

`else {`

`goatOne = 0;`

`goatTwo = 1;`

`}`

`// So:`

`// contents[carIdx] == true`

`// contents[goatOne] == false`

`// contents[goatTwo] == false`

`assert( contents[carIdx] );`

`assert( ! contents[goatOne] );`

`assert( ! contents[goatTwo] );`

`// Simulate an initial choice, then expose a goat:`

`int userChoice = rand() % 3;`

`int doorExposed = (goatOne==userChoice)?goatTwo:goatOne;`

`// Do we change doors?`

`bool changedDoors = rand() % 2;`

`if ( changedDoors ) {`

`changedDoorCount++;`

`// Pick the door that isn't the user's choice`

`// and isn't the exposedDoor... note:`

`//`

`// userChoice != doorExposed by design.`

`if ( userChoice == 0 )`

`{`

`if ( doorExposed == 1 )`

`userChoice = 2;`

`else`

`userChoice == 1;`

`}`

`else if ( userChoice == 1 )`

`{`

`if ( doorExposed == 0 )`

`userChoice = 2;`

`else`

`userChoice = 0;`

`}`

`else`

`{`

`if ( doorExposed == 0 )`

`userChoice = 1;`

`else`

`userChoice = 0;`

`}`

`assert( userChoice != doorExposed ); }`

`// Track how many times we chose correctly -`

`// Increment correct[0] if we kept our original choice`

`// Increment correct[1] if we chose the other door.`

`if ( contents[userChoice] ) {`

`correct[ changedDoors ]++; } }`

`double changedWinPercent =`

`100`

(correct[1]/static_cast(changedDoorCount));

doubleoriginalWinPercent=

100(correct[0]/static_cast(iterations-changedDoorCount)); double totalWinPercent = (correct[0]+correct[1]) / static_cast( iterations ) * 100; cout << "In " << iterations << " runs, we won a car " << totalWinPercent << "% of the time." << endl; cout << "\tUsed original choice and won a car " << correct[0] << " out of " << iterations - changedDoorCount << " times… " << originalWinPercent << "%" << endl; cout << "\tChose the other door and won a car " << correct[1] << " out of " << changedDoorCount << " times… " << changedWinPercent << "%" << endl; }