The Monty Hall Problem - C# Solution






3.56/5 (9 votes)
C# Solution to the "Monty Hall Problem"
Introduction
In a recent episode of Numb3rs, the television drama sometimes involving the theoretical use of mathematics to solve real world crime problems "Charlie" the Mathematician gave a public seminar demonstrating some math's puzzles. One of those demonstrated was the "Monty Hall Paradox" Wikipedia describes this puzzle as:
"The Monty Hall problem is a puzzle involving probability loosely based on the American game show Let's Make a Deal. The name comes from the show's host, Monty Hall. A widely known, but problematic (see below) statement of the problem is from Craig F. Whitaker of Columbia, Maryland in a letter to Marilyn vos Savant's September 9, 1990, column in Parade Magazine (as quoted by Bohl, Liberatore, and Nydick).
Suppose you're 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 No. 1, and the host, who knows what's behind the doors, opens another door, say No. 3, which has a goat. He then says to you, "Do you want to pick door No. 2?" Is it to your advantage to switch your choice?"
The question in a nutshell is, after the host removes one of the wrong doors, is there any advantage to changing your answer. Is it now a 50/50 chance? Or does staying or changing your selection increase OR decrease your odds of winning?
The Experiment
I wrote a simple console application that run 1 million iterations of The Monty Hall gameshow segment. The proof carries out the following process:
- Randomly choose 1 of 3 doors for the initial contestant's pick
- Randomly pick one of the wrong doors to remove (the host knows which one has the car, and removes an INCORRECT choice)
- Change the contestant's picked door
- Determine if the contestant WON or LOST!
Did the contestant win after switching?
Result when SWITCHING your choice after the host has removed one incorrect answer:
Wins: 666576 Losses: 333424 Total: 1000000
If you initially think that there is no advantage in switching doors, or your probability is 50/50, or your probability remains at 1 out of 3 - you are in great company, but still INCORRECT.
Switching your initial choice after the host has disclosed one incorrect door DOUBLES your chances of winning to 2 out of 3.
I must admit, until I wrote this proof I wasn't exactly confident. It clearly demonstrates that approximate 66% of the time you would WIN if you SWITCHED your answer, and only win 33% of the time if you kept your initial choice.
I was also amazed at the almost perfect ratio 66.6 / 33.3 which matched the theoretical 2 out of 3 win/loss prediction. Kudos to the authors of the built-in .NET Random class. I didn't initially believe the results because the numbers worked out so nice, but I've double-checked my code and made certain that I've used random decisions for all moving parts. I'd be interested if anyone can point-out anything wrong with my code though.
The Code
using System;
namespace MontyHall
{
class Program
{
static void Main(string[] args)
{
// local variables to hold result and random generator
Random random = new Random();
int wins = 0;
int losses = 0;
// iterate our MontyHall routine
for (int i = 0; i < 1000000; i++)
{
// changeDoor:
// 0 = no, the contestant stays with their initial pick,
// after the offer to switch after
// the disclosure of a "Goat" door
// 1 = yes, the contestant chose to switch doors after
// the disclosure of a "Goat" door
//int changeDoor = 0;
int changeDoor = 1;
// calculate whether or not the contestant wins the Car -
// random pickedDoor: 0, 1 or 2 for the door
// the contestant initially picked
// changeDoor: 0 = no, 1 = yes. The contentment decides
// to change their selection after disclosure of a "Goat" door
// random carDoor: 0, 1 or 2 for the door containing the car
// random goatDoorToRemove: 0 = leftmost Goat door,
// 1 = rightmost Goat door. Monty discloses
// one incorrect door, this value indicates which one.
bool result = MontyHallPick(random.Next(3), changeDoor,
random.Next(3), random.Next(1));
if (result)
wins++;
else
losses++;
}
Console.WriteLine("Wins: {0} Losses: {1} Total: {2}",
wins, losses, wins+losses);
Console.ReadLine();
}
public static bool MontyHallPick(int pickedDoor, int changeDoor,
int carDoor, int goatDoorToRemove)
{
bool win = false;
// randomly remove one of the *goat* doors,
// but not the "contestants picked" ONE!
int leftGoat = 0;
int rightGoat = 2;
switch (pickedDoor)
{
case 0: leftGoat = 1; rightGoat = 2; break;
case 1: leftGoat = 0; rightGoat = 2; break;
case 2: leftGoat = 0; rightGoat = 1; break;
}
int keepGoat = goatDoorToRemove == 0 ? rightGoat : leftGoat;
// would the contestant win with the switch or the stay?
if (changeDoor == 0)
{
// not changing the initially picked door
win = carDoor == pickedDoor;
}
else
{
// changing picked door to the other door remaining
win = carDoor != keepGoat;
}
return win;
}
}
}