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.";

Replies are listed 'Best First'.
Re: The Monty Hall Trap Simulator
by Abigail-II (Bishop) on Jul 16, 2002 at 13:26 UTC
I did find your logic a bit hard to follow, so I coded an alternative. It does 10,000 runs with 2 contestants, one of which will always swap, and one will never. Number of doors, the number of revealed doors and the number of runs can be varied with command line options.
```#!/usr/bin/perl

use strict;
use warnings 'all';

use Getopt::Long;

GetOptions   'doors=i'    =>  \(my \$doors   =      3),
'reveals=i'  =>  \(my \$reveals =      1),
'runs=i'     =>  \(my \$runs    = 10_000),
or exit 1;

# Sanity checks.
\$doors   = 3 if \$doors   < 3;
\$reveals = 1 if \$reveals < 1;
\$runs    = 1 if \$runs    < 1;
\$reveals = \$doors - 2 if \$reveals + 2 > \$doors;

use constant  GOAT    =>  0x00;
use constant  PRICE   =>  0x01;
use constant  PICK    =>  0x02;
use constant  REVEALS =>  0x04;

my (\$non_swapper, \$swapper) = (0) x 2;
foreach (1 .. \$runs) {
# Put goats behind the doors.
my @doors = (GOAT) x \$doors;

# Upgrade one goat to the price.
\$doors [my \$price  = int rand @doors] |= PRICE;

# Our contestants pick a door.
\$doors [my \$f_pick = int rand @doors] |= PICK;

# Doors Monty can reveal.
my @monties = grep {!\$doors [\$_]} 0 .. \$doors - 1;

# Monty reveals doors.
my \$r = \$reveals;
while (@monties && \$r --) {
\$doors [splice @monties, rand @monties, 1] |= REVEALS;
}

# Swap.
my @closed = grep {!(\$doors [\$_] & REVEALS) &&
!(\$doors [\$_] & PICK)} 0 .. \$doors - 1;
my \$s_pick = \$closed [rand @closed];

\$non_swapper ++ if \$price == \$f_pick;
\$swapper ++ if \$price == \$s_pick;
}

printf "\$runs runs with \$doors doors. Monty reveals \$reveals closed do
+or%s.\n",
\$reveals == 1 ? "" : "s";
printf "The non swapping contestant won %.2f%% of the prices.\n",
100 * \$non_swapper / \$runs;
printf "The swapping contestant won %.2f%% of the prices.\n",
100 * \$swapper / \$runs;

Abigail

by BigLug (Chaplain) on Jul 16, 2002 at 12:07 UTC
Don't you hate it when you forget to log in before you post ... anyways, that's mine above. By the way, this link has a great description of the problem.

If you don' t believe my reasoning above, think about this: What if there were 100 doors, you picked one, Mr Hall reveals 98. This means you were either right the first time (1% chance) or you should swap (99% chance). To check this out, just change the \$Doors to 100 above.

Great discussion on the Monty Hall problem
by laughingboy (Monk) on Jul 16, 2002 at 17:13 UTC
Ah, yes, the infamous Monty Hall problem, tailor made for starting fist fi... er, I mean, stimulating critical thinking and philosophical discussion.

There are actually a lot of subtleties buried in this and related probability questions. The best (and funniest) explanation and discussion on this topic I've ever seen is here .

Yes, this post is just a thinly disguised excuse to promote what I think is the most consistently funny and educational site on the web .

ObPerl: Cecil would make a great Perl programmer.

laughingboy

OK, I say pigeons don't bob their heads.  They hold them still, then hurry to catch up.

p
Re: Monty Hall (Russ: Bridge calls it "Restricted Choice")
by Russ (Deacon) on Jul 18, 2002 at 01:07 UTC
This reminds me of a well-known principle in advanced Duplicate Bridge play called the "Principle of Restricted Choice."

In a nutshell (translating Monty Hall into a Bridge-like situation), if you have chosen the wrong door, Monty only has one choice; he must pick the wrong door. If you had already chosen the correct door, both of his choices would be equally wrong.

Now (here's the tricky part), since he has picked one door, we know that if you are right, he could have picked the other door. Since he didn't pick it, you should. The odds are in your favor if you do.

Too much fun :-)

I looked for a good "Restricted Choice" link, but this was the best I could do on short notice

Russ
Brainbench 'Most Valuable Professional' for Perl

Re: The Monty Hall Trap Simulator
by rsmorawski (Initiate) on Jul 17, 2002 at 18:37 UTC
Assuming monty *always* opens a wrong door

You have a critical flaw in your logic. You assume that your original choice has anything to do with the chance of you winnning.. And it doesn't. Your first choice is irrelevant. When monty asks you to switch you always have the option of picking from one of 2 doors. One that will win, and one what will loose.

Agreed, when you remove 1 door, you still have a .333 chance that your ORIGINAL decision is correct. HOWEVER, once one door is removed, you are left with a new choice between 2 doors. One being the car, and one being the goat. You now have a .5 chance of walking away with a goat, but a .333 chance that your original guess is correct.

The probablilty of you being right on your first choice is ALWAYS .333, HOWERVER the probability of you winning is ALWAYS .5

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

Sure, go ahead... You still have the same shot at winning.

Rick
Not to be a pedant, but you're wrong. The problem is not quite as you stated it. The problem is, "Given three doors, and the following cirumstances, what's your chance to win if you switch?" Your restatement is, "Given two doors, what's your chance to win?" Your answer is correct for your problem, but your problem is different from what we're discussing here.
--
man with no legs, inc.
Yes.. The original poster was absolutely correct. As are you.

Here is the logic I used to realize my mistake (that and 3 pieces of paper ;) )

If you pick a loosing door, and monty removes a loosing door, 100% of the time you will win if you switch.

Since you have a .66 chance of picking a loosing door, you have a .66 chance of winning when switching.

Rick
Re: The Monty Hall Trap Simulator
by zakzebrowski (Curate) on Jul 17, 2002 at 17:17 UTC
(Man, I'm tired... when I was orignally scanning, I thought it said the classic Monty Python problem...)

That rabbit's dynamite!

----
Zak
"There is no room in this country for hyphenated Americanism" ~ Theodore Roosevelt (1915)