A little program in RubyLanguage to simulate the MontyHallProblem. We were going to do it in PythonLanguage, but then we'd have to call it MontyPython.
def randomDoor return rand(3) end def otherDoorThan(*forbiddenDoors) allowedDoors = [0,1,2] - forbiddenDoors return allowedDoors[rand(allowedDoors.size)] end stayingWasRight = 0 changingWasRight = 0 1_000_000.times do prizeDoor = randomDoor() firstChosenDoor = randomDoor() montysDoor = otherDoorThan(prizeDoor, firstChosenDoor) secondChosenDoor = otherDoorThan(montysDoor, firstChosenDoor) case prizeDoor when firstChosenDoor then stayingWasRight += 1 when secondChosenDoor then changingWasRight += 1 else puts "Monty cheated!" end end totalRuns = stayingWasRight + changingWasRight puts "Absolute Numbers: Staying was right in #{stayingWasRight} cases Changing was right in #{changingWasRight} cases Total number of runs: #{totalRuns} Relative Numbers: Staying was right in #{100.0 * stayingWasRight / totalRuns}% cases Changing was right in #{100.0 * changingWasRight / totalRuns}% cases"A run produced the following output:
Absolute Numbers: Staying was right in 333810 cases Changing was right in 666190 cases Total number of runs: 1000000 Relative Numbers: Staying was right in 33.381% cases Changing was right in 66.619% casesSo this supports the notion, that changing is right in 2/3 of the cases. Or can you spot any problems in this program, similar to the problems some of the tables on MontyHallProblem have?
Writing my own MontyHallSimulation made the solution clearer to me. I was able to simplify it to something like this:
prizeDoor = randomDoor(); firstChosenDoor = randomDoor(); if prizeDoor == firstChosenDoor then stayingWasRight += 1 else changingWasRight += 1 endAnd clearly, prizeDoor == firstChosenDoor only 1/3 of the time.
This is correct, but doesn't really show why the problem is different from NotTheMontyHallProblem. For that, see NotMontyHallSimulation -- AndrewMcGuinness
The only reason you could reduce the problem to above, is because you had done the analysis. So it isn't really a simulation, per se.
Here is a simulation done in lisp. It is somewhat redundant, as no analysis of the choices is done:
(defun monty-hall (N) "simulate the 'Monty Hall' problem for N iterations" (defun pick-one (list) (nth (random (length list)) list)) (let ((stay-success 0) (switch-success 0)) (dotimes (i N t) (let* ((doors (list 0 1 2)) (prize-door (pick-one doors)) (your-door (pick-one doors)) (monty-door (pick-one (remove prize-door (remove your-door doors)))) (switch-door (pick-one (remove monty-door (remove your-door doors))))) (cond ((equal your-door prize-door) (incf stay-success)) ((equal switch-door prize-door) (incf switch-success))))) (list stay-success switch-success)))and output for a run:
* (monty-hall 100000000) (33337404 66662596)
A Java applet (with source code) is available here: http://www.rdrop.com/~half/Creations/Puzzles/LetsMakeADeal/monty.hall.applet.html
This applet lets you play the game manually, or the applet can play itself. There are three-door and six-door versions, and running win/lose statistics are displayed as you play.
Here's a version in Perl, loosely based on the Ruby version above, but altered slightly to allow for more than three doors (if desired).
use strict; use warnings; my $number_of_doors = 3; my $total_trials = 1_000_000; sub random_door { return int rand $number_of_doors; } sub door_other_than { my @forbidden = @_; my %doors; @doors{ 0 .. $number_of_doors - 1 } = (); for my $door (@forbidden) { delete $doors{$door}; } my @choose_from = keys %doors; return $choose_from[ int rand @choose_from ]; } my $staying_was_right = 0; my $changing_was_right = 0; for (1 .. $total_trials) { my $prize_door = random_door(); my $first_chosen_door = random_door(); my $montys_door = door_other_than($prize_door, $first_chosen_door); my $second_chosen_door = door_other_than($montys_door, $first_chosen_door); if ($prize_door == $first_chosen_door) { $staying_was_right++ } elsif ($prize_door == $second_chosen_door) { $changing_was_right++; } } my $stay_percent = 100 * $staying_was_right / $total_trials; my $change_percent = 100 * $changing_was_right / $total_trials; print <<END_TEXT; Total trials: $total_trials Absolute numbers: Staying was right in $staying_was_right cases. Changing was right in $changing_was_right cases. Relative numbers: Staying was right in $stay_percent% cases. Changing was right in $change_percent% cases. END_TEXT