Tuesday, February 24, 2015

You can't beat Monty Hall

Recently, I was introduced by my girlfriend to the Monty Hall Problem-- an age old probability which places you as a game show contestant, with the opportunity of winning a sports car. There are doors, and all you have to do is select which one of the three doors contains the car-- because the other two contain goats. The story goes that you choose a door, and then Monty Hall, the imagined host of this gameshow, reveals one of the doors containing a goat. At this point you're given the opportunity to stay with your current door, or to switch to the other door.

The controversy of this problem is that while it is assumed that you have 50/50 chance at winning the sports car, it is in fact more likely that you will win if you switch. 

If you are not familiar with the problem, this will likely when you begin to doubt. Thankfully, you're not alone, as I too found myself in disbelief that such a simple scenario could be any more than it seems. While I was able to find solace thanks to the brilliant folks at Numberphile, I still felt that the best way to prove to myself that this was true was to create a computer simulation.

I immediately got to work in Racket-- one of my languages of study in my Programming Languages course-- forming an effective simulation for any size of games. This was accomplish through the use of several structs, namely
  • Monty, three binary digits representing which door contains the car;
  • Choice, three digits representing the player's random choice where
    • 1 represents the player's randomized choice
    • 0 represents the door that was not chosen
    • -1 represents the door the host revealed to have a goat.
  •  Gameshow, which is composed of a Choice and a Monty.
From this point it was all about being able to initiate each struct, form each struct into a list, randomize each struct, and form a list composed of each struct. This sometimes required that functions simply passed fewer arguments to "handler" functions that either formed the structs into lists, or called substructs.

Once I had finished, the moment of truth was quit exhilarating. I watched the results compile, and sure enough, the distribution very closely modeled 1:3 for staying and 2:3 for switching. Below are two screenshots of models I used, the first being of size 10^3, and then 10^6 (which took quite a while on my crappy hardware!).



This got me really excited about constructing a computer cluster and using parallelism to tackle these huge problems. 

Of course, I've made my code available at Github for those of you who would like to give it a try. Soon, I'll be reproducing the code in Haskell for a presentation in class Friday. I'll be trying to model it as close as possible, so hopefully anyone can use it to "benchmark" (the term must always be used lightly) Haskell and Racket. As part of my presentation, I plan to do the same.

No comments:

Post a Comment