Empirical solution of the Monty Hall problem
|
Programs for computing empirical solutions to the Monty Hall problem are given in both Perl and Java.
Perl solution
The following Perl program computes an approximate solution of the Monty Hall problem by simulation. Two strategies are simulated: stick with initial choice every time, or switch from initial choice every time. The program performs a number of games and counts how many times each strategy wins the game.
The result of the simulation almost always shows that the switch strategy wins about twice as many times as the stick strategy. This is empirical evidence that switching is a better strategy in this game.
#!/usr/bin/perl # Approximate solution of the Monty Hall problem # Use -v to see each game. (default: off) # Use -i # to set number of iterations. (default: 3000) use strict; my $iterations = 3000; # How many games to play my $verbosity = 0; while (@ARGV) { my $param = shift @ARGV; $verbosity = 1 if $param eq '-v'; $iterations = int (shift @ARGV) if $param eq '-i'; } sub verbose { print $_[0]."\n" if $verbosity; } my $stickers; my $switchers; print "Playing $iterations games...\n\n"; for(1..$iterations) { my @items = qw(goat goat prize); # two goats, one prize my @door; while (@items) { # put the @items into the @door array in random order push (@door, splice (@items, int rand @items, 1)); } verbose ("Door 0: $door[0]; Door 1: $door[1]; Door 2: $door[2]"); my $contestant = int rand 3, my $monty, my $alternate; # If the contestant picked the prize, Monty picks another door at random. if ($door[$contestant] eq 'prize') { $monty = ($contestant + (int rand 2) + 1) % 3; } # Otherwise, he picks the other goat. else { $monty = $door [ ($contestant+1) % 3 ] eq 'goat' ? ($contestant+1) % 3 : ($contestant+2) % 3; } $alternate = ($contestant + 1) % 3 == $monty ? ($contestant + 2) % 3 : ($contestant + 1) % 3; verbose ("Contestant opens door $contestant, Monty opens door $monty; alternate is $alternate."); if ($door[$contestant] eq 'prize') { verbose ("Sticker wins."); $stickers++; } if ($door[$alternate] eq 'prize') { verbose ("Switcher wins."); $switchers++; } } print "Grand totals: Sticker has won $stickers times Switcher has won $switchers times ";
Here is the output of a sample run of this program for the default 3000 iterations:
Playing 3000 games... Grand totals: Sticker has won 1013 times Switcher has won 1987 times
Java solution
The following Java program simulates a million games and compares the success rate of the switching strategy with that of the staying strategy.
import java.security.SecureRandom; public class MontyHall { public static void main(String[] args) { SecureRandom rand = new SecureRandom(); int games = 1000000, winsWithSwitch = 0, winsWithoutSwitch = 0; System.out.println("Playing " + games + " games..."); for(int i = 0; i < games; i++) { // Place the prize behind a door, and then let the // contestant choose. int prizeDoor = rand.nextInt(3); int choice = rand.nextInt(3); // Open a door that does not have the prize behind it. int openedDoor; if(choice == prizeDoor) openedDoor = (prizeDoor + 1 + rand.nextInt(2)) % 3; else openedDoor = (0 + 1 + 2) - choice - prizeDoor; // Let the contestant switch to the door that was NOT opened. int switchDoor = (0 + 1 + 2) - choice - openedDoor; if(choice == prizeDoor) winsWithoutSwitch++; if(switchDoor == prizeDoor) winsWithSwitch++; } System.out.print("Win rate with a \"don't switch\" strategy: "); System.out.println((double) winsWithoutSwitch / games); System.out.print("Win rate with a \"switch\" strategy: "); System.out.println((double) winsWithSwitch / games); } }