65.9K
CodeProject is changing. Read more.
Home

The Monty Hall Problem - C# Solution

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.56/5 (9 votes)

Nov 1, 2006

CPOL

3 min read

viewsIcon

98796

downloadIcon

328

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 ParadoxWikipedia 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:

  1. Randomly choose 1 of 3 doors for the initial contestant's pick
  2. Randomly pick one of the wrong doors to remove (the host knows which one has the car, and removes an INCORRECT choice)
  3. Change the contestant's picked door
  4. 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;
        }
    }
}