Login


Simulating the Monty Hall Problem

By Jonathan Wood on 7/6/2014
Language: C#
Technology: .NET
Platform: Windows
License: CPOL
Views: 480
General Programming » Simulations » General » Simulating the Monty Hall Problem

Monty Hall Demo Application

Download Project Source Code Download Project Source Code

Introduction

The Monty Hall Problem is a brain teaser based on the old Let's Make a Deal game show. It became a well-know question from a reader's letter quoted in Marilyn vos Savant's "Ask Marilyn" column in Parade magazine in 1990. The somewhat unintuitive nature of the puzzle caused many readers to refuse to believe Maryilyn's answer to the question.

The puzzle goes like this: you are on a game show and are presented with three curtains. You are told that there is a new car behind one of the curtains, and a goat is behind each of the two remaining curtains. If you choose the curtain with the car, then you win the car. So you choose one curtain.

At this point, your odds of winning are 1 in 3. But then the game show host reveals what's behind one of the curtains that you did not choose, and he reveals a curtain that contains a goat. The host then says that you may change your choice to the one remaining curtain, if you like. The question then is if your odds of winning the car will increase if you switch your selection.

Marilyn's answer was that it does increase your odds of winning. Personally, I had to struggle with this one myself until I understood that when the host reveals what's behind one of the curtains, he is providing you with information you didn't originally have about what is behind the curtains. And, in fact, if you switch your selection, your odds of winning go from 1 in 3 up to 2 in 3.

So I was thinking about this puzzle recently and found it interesting enough that I wanted to put it to the test. I thought it would be a fun little project to simulate this situation and confirm for myself what the results would be.

Presenting the Code

The code for this project is not at all complex. All that is needed is to randomly select one of three choices for the car, randomly select one of three choices again for the contestant's choice, and then randomly select another one of three choices--one that is neither the curtain with the car or the one chosen by the contestant. The code needs two modes: one were the contestant's first choice is kept, and another where their choice is switched after the reveal.

Note that the code to perform the reveal serves no purpose when the contestant does not switch their choice, but that logic is still executed anyway (for no particular reason).

Listing 1 shows my RunTest() method. This is the heart of the simulation. The two arguments determine how many simulations to perform and whether or not the choice should be switched after the reveal.

Listing 1: The RunTest() Method

protected string RunTest(int simulationCount, bool switchAfterReveal)
{
    const int NumCurtains = 3;
    Random rand = new Random();
    int total = 0;
    int wins = 0;

    for (int i = 0; i < simulationCount; i++)
    {
        // Set curtain that contains car
        int car = rand.Next(NumCurtains);

        // Contestant chooses a curtain
        int choice = rand.Next(NumCurtains);

        // Monty reveals a curtain (If the original choice is the curtain with the
        // car then Monty can reveal either of the two remaining curtains. So make
        // a random selection for the revealed curtain to handle this case.)
        var choices = Enumerable.Range(0, NumCurtains).Where(j => j != car && j != choice);
        int reveal = choices.ElementAt(rand.Next(choices.Count()));

        // Switch choice to remaining curtain if requested
        if (switchAfterReveal)
            choice = Enumerable.Range(0, NumCurtains).Single(j => j != choice && j != reveal);

        // Save result
        total++;
        if (choice == car)
            wins++;
    }

    // Result result
    return String.Format("Simulations: {0:#,##0}, Wins: {1:#,##0} ({2:0.0}%), Switched after Reveal: {3}",
        total,
        wins,
        ((double)wins / (double)total) * 100.0,
        switchAfterReveal ? "Yes" : "No");
}

Conclusion

If you like, you can download the project to try it for yourself. As you can see from the screenshot above, the odds of winning are around 1 in 3 and 2 in 3, depending on whether the contestant switches their choice after the reveal.

As you can see, Marilyin was right!

End-User License

Use of this article and any related source code or other files is governed by the terms and conditions of The Code Project Open License.

Author Information

Jonathan Wood

I'm a software and website developer working out of the greater Salt Lake City area of Utah. I've developed many websites including Black Belt Coder, Trail Calendar, and others.

I hike each week with my dogs Suki and Sasha. You can see my hiking blog at Hiking Salt Lake.