http://www.perlmonks.org?node_id=182046

The Monty Hall Trap is a math problem based on US TV's Lets Make a Deal. On the game show the host (Monty Hall) allows a contestant to choose their prize. However, the three prizes to choose from are hidden behind three doors. The contestant chooses a door, Mr Hall opens one of the other doors and asks the contestant if they want to change to the other door.

Most people, when asked if they should change will tell you that the probability is 50/50 (or 0.5). However, this is not so.

The probability of getting it right the first time is 0.333 (a 1 in 3 chance of getting it right). Mr Hall then opens another door, leaving you with two doors closed. One has the car, the other has a goat. Its normal to guess that with two doors, the probability is 0.5, however probability does not change when a non-essential alteration is made (that is, when he opens a door that isn't the one you picked, the proability of you being right is still 0.333). Thus, as all probabilities have to add up to 1, the chance of it being the other door is 0.666.

If you're ever on the show this means you should change your door!

What has this to do with Perl? Well the following code will allow you to test this theory through running any number of games. I've also set it up to allow you to set the number of doors, and the number of doors Mr Hall reveals (set it to >0 for a set number of doors, or a negative number to make it relative to the number of doors: '-1' means open all but your guess and one other door, '-2' means all but your guess and two other doors)

#!/usr/bin/perl #--------------------------------------------------------------------- +----------- # Monty Hall Trap #--------------------------------------------------------------------- +----------- $Number_of_games_to_play = 100; # Set to any number of games. $Doors = 3; # Total number of doors on the se +t $Reveal = -1; # >0 means to reveal that number +or doors # <0 means to reveal $Doors+$Reve +al-1 # (or just leave you with # one door to swap to) $Verbose = 1; # Print the results for each game $Swap_Option = 1; # -1 Never swap # 0 Sometimes swap # 1 Always swap doors #--------------------------------------------------------------------- +----------- # The following code plays the game and there is no need to change any +thing. #--------------------------------------------------------------------- +----------- # Set the reveal if its 0 or a negative number if ($Reveal < 1) { $Reveal = $Doors + $Reveal - 1; } die ("Reveal was too high.") if $Reveal >= ($Doors - 1); $Game_Number = 1; $Correct = 0; $Swapped = 0; for $Game_Number ( 1 .. $Number_of_games_to_play ) { #Seed the doors: @Door_Flags = (); for (1..$Doors) { push(@Door_Flags,' ') } $This_Games_Correct_Door = int(rand($Doors)+1); $Door_Flags[$This_Games_Correct_Door] = 'W'; print "Game $Game_Number: Door $This_Games_Correct_Door\n" if $Ver +bose; $This_Games_Guess = int(rand($Doors)+1); $Door_Flags[$This_Games_Guess] = 'G'; print "Game $Game_Number: Guess $This_Games_Guess\n" if $Verbose; for $r ( 1 .. $Reveal ) { $Game_Reveal = int(rand($Doors)+1); $break=0; while (($Door_Flags[$Game_Reveal]=~/\w/) &amp;&amp; ($break < +10000)) { $break++; $Game_Reveal = int(rand($Doors)+1); } last if ($break >= 10000); $Door_Flags[$Game_Reveal] = 'R'; print "Game $Game_Number: Reveal $Game_Reveal\n" if $Verbose; } $Swap = ($Swap_Option) ? $Swap_Option+1 : int(rand(2)); if ($Swap) { $s=0; do {$s++} until (($Door_Flags[$s] ne 'R') &amp;&amp; ($s != $T +his_Games_Guess)); $This_Games_Guess = $s; $Swapped++; print "Game $Game_Number: Changed my guess to $This_Games_Gues +s\n" if $Verbose; } if ($This_Games_Guess == $This_Games_Correct_Door) { print "YOU WIN!\n" if $Verbose; $Correct++; } else { print "You lose.\n" if $Verbose; } print "Doors: " . join('|',@Door_Flags) . "|\n" if $Verbose; print "\n" if $Verbose; } print "I played $Number_of_games_to_play games and won $Correct. I swa +pped my guess on $Swapped games.";