Monty Hall / Let’s Make a Deal problem simulator
July 3rd, 2005 by ThomasI found this post about the Monte Hall problem on the Singularity blog and couldn't help but writing a little simulator...
I'm not going into the details again - it's a quite fascinating statistical problem that appeared in a US game show and apparently caused quite some controversy (here's a another good explanation).
I took the opportunity to try out FAME, which worked nicely thanks to the excellent first step tutorial by Carlos Rovira's (Towards Open Source Flash Development).
It might be worth mentioning that the latest version of Flashout only works with Eclipse 3.1.
Sample swf:
[flash]http://www.blog.lessrain.com/wp-content/upload/makeadeal.swf,500,100[/flash]
-> Et voilà - we truly double our chances by switching the door!
Click here to download the source
This is the main class doing the simulation:
- /**
- * @author lessrain
- */
- import lessrain.experiments.makeadeal.ScoreBoard;
- class lessrain.experiments.makeadeal.MakeADeal
- {
- static private var scoreBoard:ScoreBoard;
- static private var games:Number = 1000;
- static private var verbose:Boolean = false;
- public static function main():Void
- {
- Stage.scaleMode="noScale";
- Stage.align="TL";
- scoreBoard = new ScoreBoard(_root);
- if (verbose) games=1;
- simulate();
- }
- public static function simulate()
- {
- scoreBoard.reset();
- var startTime:Number = (new Date).getTime();
- var switchWins:Number=0;
- var stickWins:Number=0;
- // play games by switching the door at the end and count how many times the prize has been won
- if (verbose) scoreBoard.addMessage("--------------------------------------------<br><b>Switching the door</b>");
- for (var i : Number = 0; i <games; i++)
- {
- switchWins += (new MakeADeal(true)).play();
- }
- // play games by sticking with the initially selected door and count how many times the prize has been won
- if (verbose) scoreBoard.addMessage("--------------------------------------------<br><b>Sticking with the initially selected door</b>");
- for (var i : Number = 0; i <games; i++)
- {
- stickWins += (new MakeADeal(false)).play();
- }
- // output the stats
- if (verbose) scoreBoard.addMessage("--------------------------------------------<br><b>Results</b>");
- scoreBoard.displayScore(switchWins, stickWins, games, ((new Date).getTime() - startTime));
- }
- private var switchDoor:Boolean;
- private var availableDoors:Array;
- private var prizeDoor:Number;
- private var choiceDoor:Number;
- private var openDoor:Number;
- public function MakeADeal( switchDoor:Boolean )
- {
- this.switchDoor = switchDoor;
- availableDoors = [ 1, 2, 3 ];
- // choose the door with the prize
- prizeDoor = Math.floor(Math.random()*3)+1;
- if (verbose) scoreBoard.addMessage("Prize is hidden behind door <b>"+prizeDoor+"</b>");
- }
- // returns 1 if the prize was won, 0 if not
- public function play():Number
- {
- // choose a door
- choiceDoor = selectDoor(false);
- if (verbose) scoreBoard.addMessage("Player selects door <b>"+choiceDoor+"</b>");
- // if we don't want to switch it doesn't matter what happens next so let's already check if we have a winner
- if (!switchDoor) return ( choiceDoor==prizeDoor ? 1 : 0 );
- // continue if we do want to switch...
- // select (actually open) a bad door from the 2 remaining doors
- openDoor = selectDoor(true);
- if (verbose) scoreBoard.addMessage("Host opens bad door <b>"+openDoor+"</b>");
- // select the remaining door and check if it's a winner!
- return ( selectDoor(false)==prizeDoor ? 1 : 0 );
- }
- // selects a random door from all available doors stored in availableDoors and deletes it from there
- // if avoidPrizeDoor is true, it'll only return a non-prize door
- private function selectDoor( avoidPrizeDoor:Boolean ):Number
- {
- //Flashout.info("available doors: "+(availableDoors.toString()));
- // if we have to avoid the prize door, create a new array with the bad doors only
- // otherwise use all doors
- var doors:Array;
- if (avoidPrizeDoor)
- {
- doors = new Array();
- for (var i : Number = availableDoors.length-1; i>=0 ; i--)
- {
- if (availableDoors[i]!=prizeDoor) doors.push(availableDoors[i]);
- }
- }
- else doors=availableDoors;
- // select a random door
- var door:Number = doors[Math.floor(Math.random()*doors.length)];
- // remove that door from the list of available doors
- for (var i : Number = availableDoors.length-1; i>=0 ; i--)
- {
- if (availableDoors[i]==door)
- {
- availableDoors.splice(i,1);
- break;
- }
- }
- // and return it
- return door;
- }
- }



July 3rd, 2005 at 4:11 pm
I think this is the condition that all the confusion turns on
3: The host knows in advance which door contains the prize and always opens a door containing the non-desirable item before offering the choice to switch or stay.
This condition is often not stated in the problem, and slight changes to it can change the whole problem. If that condition were
3: The host doesn’t know where the prize is and always opens one of the the two remaining doors randomly.
Then the whole problem changes.
Furthermore, if you don’t know what rules the host is playing by, and if the host may actually be trying to trick you, then it becomes a really interesting exercise in Game Theory.
July 13th, 2005 at 8:39 pm
The mistake is simply that people think they have a fifty fifty chance with each remaining door after a mule is revealed. Obviously that’s not the case - the initally selected door keeps its 1 in 3 chance of winning from the beginning of the game.
It is quite mind bending though…
November 27th, 2007 at 1:49 am
[…]