This commit is contained in:
Ingy döt Net 2013-04-10 21:29:02 -07:00
parent 764da6cbbb
commit db842d013d
19005 changed files with 197040 additions and 7 deletions

View file

@ -0,0 +1,7 @@
Run random simulations of the [[wp:Monty_Hall_problem|Monty Hall]] game. Show the effects of a strategy of the contestant always keeping his first guess so it can be contrasted with the strategy of the contestant always switching his guess.
:Suppose you're on a game show and you're given the choice of three doors. Behind one door is a car; behind the others, goats. The car and the goats were placed randomly behind the doors before the show. The rules of the game show are as follows: After you have chosen a door, the door remains closed for the time being. The game show host, Monty Hall, who knows what is behind the doors, now has to open one of the two remaining doors, and the door he opens must have a goat behind it. If both remaining doors have goats behind them, he chooses one randomly. After Monty Hall opens a door with a goat, he will ask you to decide whether you want to stay with your first choice or to switch to the last remaining door. Imagine that you chose Door 1 and the host opens Door 3, which has a goat. He then asks you "Do you want to switch to Door Number 2?" Is it to your advantage to change your choice? ([http://www.usd.edu/~xtwang/Papers/MontyHallPaper.pdf Krauss and Wang 2003:10])
Note that the player may initially choose any of the three doors (not just Door 1), that the host opens a different door revealing a goat (not necessarily Door 3), and that he gives the player a second choice between the two remaining unopened doors.
Simulate at least a thousand games using three doors for each strategy <u>and show the results</u> in such a way as to make it easy to compare the effects of each strategy.

View file

@ -0,0 +1,5 @@
---
category:
- Games
- Probability and statistics
note: Discrete math

View file

@ -0,0 +1,54 @@
INT trials=100 000;
PROC brand = (INT n)INT: 1 + ENTIER (n * random);
PROC percent = (REAL x)STRING: fixed(100.0*x/trials,0,2)+"%";
main:
(
INT prize, choice, show, not shown, new choice;
INT stay winning:=0, change winning:=0, random winning:=0;
INT doors = 3;
[doors-1]INT other door;
TO trials DO
# put the prize somewhere #
prize := brand(doors);
# let the user choose a door #
choice := brand(doors);
# let us take a list of unchoosen doors #
INT k := LWB other door;
FOR j TO doors DO
IF j/=choice THEN other door[k] := j; k+:=1 FI
OD;
# Monty opens one... #
IF choice = prize THEN
# staying the user will win... Monty opens a random port#
show := other door[ brand(doors - 1) ];
not shown := other door[ (show+1) MOD (doors - 1 ) + 1]
ELSE # no random, Monty can open just one door... #
IF other door[1] = prize THEN
show := other door[2];
not shown := other door[1]
ELSE
show := other door[1];
not shown := other door[2]
FI
FI;
# the user randomly choose one of the two closed doors
(one is his/her previous choice, the second is the
one not shown ) #
other door[1] := choice;
other door[2] := not shown;
new choice := other door[ brand(doors - 1) ];
# now let us count if it takes it or not #
IF choice = prize THEN stay winning+:=1 FI;
IF not shown = prize THEN change winning+:=1 FI;
IF new choice = prize THEN random winning+:=1 FI
OD;
print(("Staying: ", percent(stay winning), new line ));
print(("Changing: ", percent(change winning), new line ));
print(("New random choice: ", percent(random winning), new line ))
)

View file

@ -0,0 +1,15 @@
Run runs;doors;i;chosen;cars;goats;swap;stay;ix;prices
[1] ⍝0: Monthy Hall problem
[2] ⍝1: http://rosettacode.org/wiki/Monty_Hall_problem
[3]
[4] (⎕IO ⎕ML)0 1
[5] prices0 0 1 ⍝ 0=Goat, 1=Car
[6]
[7] ix,/{3?3}¨runs ⍝ random indexes of doors (placement of car)
[8] doors(runs 3)prices[ix] ⍝ matrix of doors
[9] stay+doors[;?3] ⍝ chose randomly one door - is it a car?
[10] swapruns-stay ⍝ If not, then the other one is!
[11]
[12] 'Swap: ',(2100×(swap÷runs)),'% it''s a car'
[13] 'Stay: ',(2100×(stay÷runs)),'% it''s a car'

View file

@ -0,0 +1,57 @@
#!/bin/gawk -f
# Monty Hall problem
BEGIN {
srand()
doors = 3
iterations = 10000
# Behind a door:
EMPTY = "empty"; PRIZE = "prize"
# Algorithm used
KEEP = "keep"; SWITCH="switch"; RAND="random";
#
}
function monty_hall( choice, algorithm ) {
# Set up doors
for ( i=0; i<doors; i++ ) {
door[i] = EMPTY
}
# One door with prize
door[int(rand()*doors)] = PRIZE
chosen = door[choice]
del door[choice]
#if you didn't choose the prize first time around then
# that will be the alternative
alternative = (chosen == PRIZE) ? EMPTY : PRIZE
if( algorithm == KEEP) {
return chosen
}
if( algorithm == SWITCH) {
return alternative
}
return rand() <0.5 ? chosen : alternative
}
function simulate(algo){
prizecount = 0
for(j=0; j< iterations; j++){
if( monty_hall( int(rand()*doors), algo) == PRIZE) {
prizecount ++
}
}
printf " Algorithm %7s: prize count = %i, = %6.2f%%\n", \
algo, prizecount,prizecount*100/iterations
}
BEGIN {
print "\nMonty Hall problem simulation:"
print doors, "doors,", iterations, "iterations.\n"
simulate(KEEP)
simulate(SWITCH)
simulate(RAND)
}

View file

@ -0,0 +1,9 @@
bash$ ./monty_hall.awk
Monty Hall problem simulation:
3 doors, 10000 iterations.
Algorithm keep: prize count = 3411, = 34.11%
Algorithm switch: prize count = 6655, = 66.55%
Algorithm random: prize count = 4991, = 49.91%
bash$

View file

@ -0,0 +1,32 @@
package {
import flash.display.Sprite;
public class MontyHall extends Sprite
{
public function MontyHall()
{
var iterations:int = 30000;
var switchWins:int = 0;
var stayWins:int = 0;
for (var i:int = 0; i < iterations; i++)
{
var doors:Array = [0, 0, 0];
doors[Math.floor(Math.random() * 3)] = 1;
var choice:int = Math.floor(Math.random() * 3);
var shown:int;
do
{
shown = Math.floor(Math.random() * 3);
} while (doors[shown] == 1 || shown == choice);
stayWins += doors[choice];
switchWins += doors[3 - choice - shown];
}
trace("Switching wins " + switchWins + " times. (" + (switchWins / iterations) * 100 + "%)");
trace("Staying wins " + stayWins + " times. (" + (stayWins / iterations) * 100 + "%)");
}
}
}

View file

@ -0,0 +1,76 @@
-- Monty Hall Game
with Ada.Text_Io; use Ada.Text_Io;
with Ada.Float_Text_Io; use Ada.Float_Text_Io;
with ada.Numerics.Discrete_Random;
procedure Monty_Stats is
Num_Iterations : Positive := 100000;
type Action_Type is (Stay, Switch);
type Prize_Type is (Goat, Pig, Car);
type Door_Index is range 1..3;
package Random_Prize is new Ada.Numerics.Discrete_Random(Door_Index);
use Random_Prize;
Seed : Generator;
Doors : array(Door_Index) of Prize_Type;
procedure Set_Prizes is
Prize_Index : Door_Index;
Booby_Prize : Prize_Type := Goat;
begin
Reset(Seed);
Prize_Index := Random(Seed);
Doors(Prize_Index) := Car;
for I in Doors'range loop
if I /= Prize_Index then
Doors(I) := Booby_Prize;
Booby_Prize := Prize_Type'Succ(Booby_Prize);
end if;
end loop;
end Set_Prizes;
function Play(Action : Action_Type) return Prize_Type is
Chosen : Door_Index := Random(Seed);
Monty : Door_Index;
begin
Set_Prizes;
for I in Doors'range loop
if I /= Chosen and Doors(I) /= Car then
Monty := I;
end if;
end loop;
if Action = Switch then
for I in Doors'range loop
if I /= Monty and I /= Chosen then
Chosen := I;
exit;
end if;
end loop;
end if;
return Doors(Chosen);
end Play;
Winners : Natural;
Pct : Float;
begin
Winners := 0;
for I in 1..Num_Iterations loop
if Play(Stay) = Car then
Winners := Winners + 1;
end if;
end loop;
Put("Stay : count" & Natural'Image(Winners) & " = ");
Pct := Float(Winners * 100) / Float(Num_Iterations);
Put(Item => Pct, Aft => 2, Exp => 0);
Put_Line("%");
Winners := 0;
for I in 1..Num_Iterations loop
if Play(Switch) = Car then
Winners := Winners + 1;
end if;
end loop;
Put("Switch : count" & Natural'Image(Winners) & " = ");
Pct := Float(Winners * 100) / Float(Num_Iterations);
Put(Item => Pct, Aft => 2, Exp => 0);
Put_Line("%");
end Monty_Stats;

View file

@ -0,0 +1,42 @@
#NoTrayIcon
#SingleInstance, OFF
#Persistent
SetBatchLines, -1
Iterations = 1000
Loop, %Iterations%
{
If Monty_Hall(1)
Correct_Change++
Else
Incorrect_Change++
If Monty_Hall(2)
Correct_Random++
Else
Incorrect_Random++
If Monty_Hall(3)
Correct_Stay++
Else
Incorrect_Stay++
}
Percent_Change := floor(Correct_Change / Iterations * 100)
Percent_Random := floor(Correct_Random / Iterations * 100)
Percent_Stay := floor(Correct_Stay / Iterations * 100)
MsgBox,, Monty Hall Problem, These are the results:`r`n`r`nWhen I changed my guess, I got %Correct_Change% of %Iterations% (that's %Incorrect_Change% incorrect). Thats %Percent_Change%`% correct.`r`nWhen I randomly changed my guess, I got %Correct_Random% of %Iterations% (that's %Incorrect_Random% incorrect). Thats %Percent_Random%`% correct.`r`nWhen I stayed with my first guess, I got %Correct_Stay% of %Iterations% (that's %Incorrect_Stay% incorrect). Thats %Percent_Stay%`% correct.
ExitApp
Monty_Hall(Mode) ;Mode is 1 for change, 2 for random, or 3 for stay
{
Random, prize, 1, 3
Random, guess, 1, 3
If (prize = guess && Mode != 3)
While show != 0 && show != guess
Random, show, 1, 3
Else
show := 6 - prize - guess
Random, change_guess, 0, 1
If (Mode = 1 || (change_guess && Mode = 2))
Return, (6 - show - guess) = prize
Else If (Mode = 3 || (!change_guess && Mode = 2))
Return, guess = prize
Else
Return
}

View file

@ -0,0 +1,19 @@
RANDOMIZE TIMER
DIM doors(3) '0 is a goat, 1 is a car
CLS
switchWins = 0
stayWins = 0
FOR plays = 0 TO 32767
winner = INT(RND * 3) + 1
doors(winner) = 1'put a winner in a random door
choice = INT(RND * 3) + 1'pick a door, any door
DO
shown = INT(RND * 3) + 1
'don't show the winner or the choice
LOOP WHILE doors(shown) = 1 OR shown = choice
stayWins = stayWins + doors(choice) 'if you won by staying, count it
switchWins = switchWins + doors(3 - choice - shown) 'could have switched to win
doors(winner) = 0 'clear the doors for the next test
NEXT plays
PRINT "Switching wins"; switchWins; "times."
PRINT "Staying wins"; stayWins; "times."

View file

@ -0,0 +1,21 @@
total% = 10000
FOR trial% = 1 TO total%
prize_door% = RND(3) : REM. The prize is behind this door
guess_door% = RND(3) : REM. The contestant guesses this door
IF prize_door% = guess_door% THEN
REM. The contestant guessed right, reveal either of the others
reveal_door% = RND(2)
IF prize_door% = 1 reveal_door% += 1
IF prize_door% = 2 AND reveal_door% = 2 reveal_door% = 3
ELSE
REM. The contestant guessed wrong, so reveal the non-prize door
reveal_door% = prize_door% EOR guess_door%
ENDIF
stick_door% = guess_door% : REM. The sticker doesn't change his mind
swap_door% = guess_door% EOR reveal_door% : REM. but the swapper does
IF stick_door% = prize_door% sticker% += 1
IF swap_door% = prize_door% swapper% += 1
NEXT trial%
PRINT "After a total of ";total%;" trials,"
PRINT "The 'sticker' won ";sticker%;" times (";INT(sticker%/total%*100);"%)"
PRINT "The 'swapper' won ";swapper%;" times (";INT(swapper%/total%*100);"%)"

View file

@ -0,0 +1,57 @@
#include <iostream>
#include <cstdlib>
#include <ctime>
int randint(int n)
{
return (1.0*n*std::rand())/(1.0+RAND_MAX);
}
int other(int doorA, int doorB)
{
int doorC;
if (doorA == doorB)
{
doorC = randint(2);
if (doorC >= doorA)
++doorC;
}
else
{
for (doorC = 0; doorC == doorA || doorC == doorB; ++doorC)
{
// empty
}
}
return doorC;
}
int check(int games, bool change)
{
int win_count = 0;
for (int game = 0; game < games; ++game)
{
int const winning_door = randint(3);
int const original_choice = randint(3);
int open_door = other(original_choice, winning_door);
int const selected_door = change?
other(open_door, original_choice)
: original_choice;
if (selected_door == winning_door)
++win_count;
}
return win_count;
}
int main()
{
std::srand(std::time(0));
int games = 10000;
int wins_stay = check(games, false);
int wins_change = check(games, true);
std::cout << "staying: " << 100.0*wins_stay/games << "%, changing: " << 100.0*wins_change/games << "%\n";
}

View file

@ -0,0 +1,23 @@
//Evidence of the Monty Hall solution.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define GAMES 3000000
int main(void){
unsigned i, j, k, choice, winsbyswitch=0, door[3];
srand(time(NULL)); //initialize random seed.
for(i=0; i<GAMES; i++){
door[0] = (!(rand()%2)) ? 1: 0; //give door 1 either a car or a goat randomly.
if(door[0]) door[1]=door[2]=0; //if 1st door has car, give other doors goats.
else{ door[1] = (!(rand()%2)) ? 1: 0; door[2] = (!door[1]) ? 1: 0; } //else, give 2nd door car or goat, give 3rd door what's left.
choice = rand()%3; //choose a random door.
//if the next door has a goat, and the following door has a car, or vice versa, you'd win if you switch.
if(((!(door[((choice+1)%3)])) && (door[((choice+2)%3)])) || (!(door[((choice+2)%3)]) && (door[((choice+1)%3)]))) winsbyswitch++;
}
printf("\nAfter %u games, I won %u by switching. That is %f%%. ", GAMES, winsbyswitch, (float)winsbyswitch*100.0/(float)i);
}

View file

@ -0,0 +1,15 @@
(ns monty-hall-problem
(:use [clojure.contrib.seq :only (shuffle)]))
(defn play-game [staying]
(let [doors (shuffle [:goat :goat :car])
choice (rand-int 3)
[a b] (filter #(not= choice %) (range 3))
alternative (if (= :goat (nth doors a)) b a)]
(= :car (nth doors (if staying choice alternative)))))
(defn simulate [staying times]
(let [wins (reduce (fn [counter _] (if (play-game staying) (inc counter) counter))
0
(range times))]
(str "wins " wins " times out of " times)))

View file

@ -0,0 +1,6 @@
monty-hall-problem> (println "staying:" (simulate true 1000))
staying: wins 337 times out of 1000
nil
monty-hall-problem> (println "switching:" (simulate false 1000))
switching: wins 638 times out of 1000
nil

View file

@ -0,0 +1,42 @@
<cfscript>
function runmontyhall(num_tests) {
// number of wins when player switches after original selection
switch_wins = 0;
// number of wins when players "sticks" with original selection
stick_wins = 0;
// run all the tests
for(i=1;i<=num_tests;i++) {
// unconditioned potential for selection of each door
doors = [0,0,0];
// winning door is randomly assigned...
winner = randrange(1,3);
// ...and actualized in the array of real doors
doors[winner] = 1;
// player chooses one of three doors
choice = randrange(1,3);
do {
// monty randomly reveals a door...
shown = randrange(1,3);
}
// ...but monty only reveals empty doors;
// he will not reveal the door that the player has choosen
// nor will he reveal the winning door
while(shown==choice || doors[shown]==1);
// when the door the player originally selected is the winner, the "stick" option gains a point
stick_wins += doors[choice];
// to calculate the number of times the player would have won with a "switch", subtract the
// "value" of the chosen, "stuck-to" door from 1, the possible number of wins if the player
// chose and stuck with the winning door (1), the player would not have won by switching, so
// the value is 1-1=0 if the player chose and stuck with a losing door (0), the player would
// have won by switching, so the value is 1-0=1
switch_wins += 1-doors[choice];
}
// finally, simply run the percentages for each outcome
stick_percentage = (stick_wins/num_tests)*100;
switch_percentage = (switch_wins/num_tests)*100;
writeoutput('Number of Tests: ' & num_tests);
writeoutput('<br />Stick Wins: ' & stick_wins & ' ['& stick_percentage &'%]');
writeoutput('<br />Switch Wins: ' & switch_wins & ' ['& switch_percentage &'%]');
}
runmontyhall(10000);
</cfscript>

View file

@ -0,0 +1,15 @@
(defun make-round ()
(let ((array (make-array 3
:element-type 'bit
:initial-element 0)))
(setf (bit array (random 3)) 1)
array))
(defun show-goat (initial-choice array)
(loop for i = (random 3)
when (and (/= initial-choice i)
(zerop (bit array i)))
return i))
(defun won? (array i)
(= 1 (bit array i)))

View file

@ -0,0 +1,18 @@
CL-USER> (progn (loop repeat #1=(expt 10 6)
for round = (make-round)
for initial = (random 3)
for goat = (show-goat initial round)
for choice = (loop for i = (random 3)
when (and (/= i initial)
(/= i goat))
return i)
when (won? round (random 3))
sum 1 into result-stay
when (won? round choice)
sum 1 into result-switch
finally (progn (format t "Stay: ~S%~%" (float (/ result-stay
#1# 1/100)))
(format t "Switch: ~S%~%" (float (/ result-switch
#1# 1/100))))))
Stay: 33.2716%
Switch: 66.6593%

View file

@ -0,0 +1,14 @@
;Find out how often we win if we always switch
(defun rand-elt (s)
(elt s (random (length s))))
(defun monty ()
(let* ((doors '(0 1 2))
(prize (random 3));possible values: 0, 1, 2
(pick (random 3))
(opened (rand-elt (remove pick (remove prize doors))));monty opens a door which is not your pick and not the prize
(other (car (remove pick (remove opened doors))))) ;you decide to switch to the one other door that is not your pick and not opened
(= prize other))) ; did you switch to the prize?
(defun monty-trials (n)
(count t (loop for x from 1 to n collect (monty))))

View file

@ -0,0 +1,31 @@
import std.stdio, std.random;
void main() {
int switchWins, stayWins;
while (switchWins + stayWins < 100_000) {
immutable carPos = uniform(0, 3); // Which door is car behind?
immutable pickPos = uniform(0, 3); // Contestant's initial pick.
int openPos; // Which door is opened by Monty Hall?
// Monty can't open the door you picked or the one with the car
// behind it.
do {
openPos = uniform(0, 3);
} while(openPos == pickPos || openPos == carPos);
int switchPos;
// Find position that's not currently picked by contestant and
// was not opened by Monty already.
for (; pickPos==switchPos || openPos==switchPos; switchPos++) {}
if (pickPos == carPos)
stayWins++;
else if (switchPos == carPos)
switchWins++;
else
assert(0); // Can't happen.
}
writefln("Switching/Staying wins: %d %d", switchWins, stayWins);
}

View file

@ -0,0 +1,83 @@
int rand(int max) => (Math.random()*max).toInt();
class Game {
int _prize;
int _open;
int _chosen;
Game() {
_prize=rand(3);
_open=null;
_chosen=null;
}
void choose(int door) {
_chosen=door;
}
void reveal() {
if(_prize==_chosen) {
int toopen=rand(2);
if (toopen>=_prize)
toopen++;
_open=toopen;
} else {
for(int i=0;i<3;i++)
if(_prize!=i && _chosen!=i) {
_open=i;
break;
}
}
}
void change() {
for(int i=0;i<3;i++)
if(_chosen!=i && _open!=i) {
_chosen=i;
break;
}
}
bool hasWon() => _prize==_chosen;
String toString() {
String res="Prize is behind door $_prize";
if(_chosen!=null) res+=", player has chosen door $_chosen";
if(_open!=null) res+=", door $_open is open";
return res;
}
}
void play(int count, bool swap) {
int wins=0;
for(int i=0;i<count;i++) {
Game game=new Game();
game.choose(rand(3));
game.reveal();
if(swap)
game.change();
if(game.hasWon())
wins++;
}
String withWithout=swap?"with":"without";
double percent=(wins*100.0)/count;
print("playing $withWithout switching won $percent%");
}
test() {
for(int i=0;i<5;i++) {
Game g=new Game();
g.choose(i%3);
g.reveal();
print(g);
g.change();
print(g);
print("win==${g.hasWon()}");
}
}
main() {
play(10000,false);
play(10000,true);
}

View file

@ -0,0 +1,313 @@
note
description: "[
Monty Hall Problem as an Eiffel Solution
1. Set the stage: Randomly place car and two goats behind doors 1, 2 and 3.
2. Monty offers choice of doors --> Contestant will choose a random door or always one door.
2a. Door has Goat - door remains closed
2b. Door has Car - door remains closed
3. Monty offers cash --> Contestant takes or refuses cash.
3a. Takes cash: Contestant is Cash winner and door is revealed. Car Loser if car door revealed.
3b. Refuses cash: Leads to offer to switch doors.
4. Monty offers door switch --> Contestant chooses to stay or change.
5. Door reveal: Contestant refused cash and did or did not door switch. Either way: Reveal!
6. Winner and Loser based on door reveal of prize.
Car Winner: Chooses car door
Cash Winner: Chooses cash over any door
Goat Loser: Chooses goat door
Car Loser: Chooses cash over car door or switches from car door to goat door
]"
date: "$Date$"
revision: "$Revision$"
class
MH_APPLICATION
create
make
feature {NONE} -- Initialization
make
-- Initialize Current.
do
play_lets_make_a_deal
ensure
played_1000_games: game_count = times_to_play
end
feature {NONE} -- Implementation: Access
live_contestant: attached like contestant
-- Attached version of `contestant'
do
if attached contestant as al_contestant then
Result := al_contestant
else
create Result
check not_attached_contestant: False end
end
end
contestant: detachable TUPLE [first_door_choice, second_door_choice: like door_number_anchor; takes_cash, switches_door: BOOLEAN]
-- Contestant for Current.
active_stage_door (a_door: like door_anchor): attached like door_anchor
-- Attached version of `a_door'.
do
if attached a_door as al_door then
Result := al_door
else
create Result
check not_attached_door: False end
end
end
door_1, door_2, door_3: like door_anchor
-- Doors with prize names and flags for goat and open (revealed).
feature {NONE} -- Implementation: Status
game_count, car_win_count, cash_win_count, car_loss_count, goat_loss_count, goat_avoidance_count: like counter_anchor
switch_count, switch_win_count: like counter_anchor
no_switch_count, no_switch_win_count: like counter_anchor
-- Counts of games played, wins and losses based on car, cash or goat.
feature {NONE} -- Implementation: Basic Operations
prepare_stage
-- Prepare the stage in terms of what doors have what prizes.
do
inspect new_random_of (3)
when 1 then
door_1 := door_with_car
door_2 := door_with_goat
door_3 := door_with_goat
when 2 then
door_1 := door_with_goat
door_2 := door_with_car
door_3 := door_with_goat
when 3 then
door_1 := door_with_goat
door_2 := door_with_goat
door_3 := door_with_car
end
active_stage_door (door_1).number := 1
active_stage_door (door_2).number := 2
active_stage_door (door_3).number := 3
ensure
door_has_prize: not active_stage_door (door_1).is_goat or
not active_stage_door (door_2).is_goat or
not active_stage_door (door_3).is_goat
consistent_door_numbers: active_stage_door (door_1).number = 1 and
active_stage_door (door_2).number = 2 and
active_stage_door (door_3).number = 3
end
door_number_having_prize: like door_number_anchor
-- What door number has the car?
do
if not active_stage_door (door_1).is_goat then
Result := 1
elseif not active_stage_door (door_2).is_goat then
Result := 2
elseif not active_stage_door (door_3).is_goat then
Result := 3
else
check prize_not_set: False end
end
ensure
one_to_three: between_1_and_x_inclusive (3, Result)
end
door_with_car: attached like door_anchor
-- Create a door with a car.
do
create Result
Result.name := prize
ensure
not_empty: not Result.name.is_empty
name_is_prize: Result.name.same_string (prize)
end
door_with_goat: attached like door_anchor
-- Create a door with a goat
do
create Result
Result.name := gag_gift
Result.is_goat := True
ensure
not_empty: not Result.name.is_empty
name_is_prize: Result.name.same_string (gag_gift)
is_gag_gift: Result.is_goat
end
next_contestant: attached like live_contestant
-- The next contestant on Let's Make a Deal!
do
create Result
Result.first_door_choice := new_random_of (3)
Result.second_door_choice := choose_another_door (Result.first_door_choice)
Result.takes_cash := random_true_or_false
if not Result.takes_cash then
Result.switches_door := random_true_or_false
end
ensure
choices_one_to_three: Result.first_door_choice <= 3 and Result.second_door_choice <= 3
switch_door_implies_no_cash_taken: Result.switches_door implies not Result.takes_cash
end
choose_another_door (a_first_choice: like door_number_anchor): like door_number_anchor
-- Make a choice from the remaining doors
require
one_to_three: between_1_and_x_inclusive (3, a_first_choice)
do
Result := new_random_of (3)
from until Result /= a_first_choice
loop
Result := new_random_of (3)
end
ensure
first_choice_not_second: a_first_choice /= Result
result_one_to_three: between_1_and_x_inclusive (3, Result)
end
play_lets_make_a_deal
-- Play the game 1000 times
local
l_car_win, l_car_loss, l_cash_win, l_goat_loss, l_goat_avoided: BOOLEAN
do
from
game_count := 0
invariant
consistent_win_loss_counts: (game_count = (car_win_count + cash_win_count + goat_loss_count))
consistent_loss_avoidance_counts: (game_count = (car_loss_count + goat_avoidance_count))
until
game_count >= times_to_play
loop
prepare_stage
contestant := next_contestant
l_cash_win := (live_contestant.takes_cash)
l_car_win := (not l_cash_win and
(not live_contestant.switches_door and live_contestant.first_door_choice = door_number_having_prize) or
(live_contestant.switches_door and live_contestant.second_door_choice = door_number_having_prize))
l_car_loss := (not live_contestant.switches_door and live_contestant.first_door_choice /= door_number_having_prize) or
(live_contestant.switches_door and live_contestant.second_door_choice /= door_number_having_prize)
l_goat_loss := (not l_car_win and not l_cash_win)
l_goat_avoided := (not live_contestant.switches_door and live_contestant.first_door_choice = door_number_having_prize) or
(live_contestant.switches_door and live_contestant.second_door_choice = door_number_having_prize)
check consistent_goats: l_goat_loss implies not l_goat_avoided end
check consistent_car_win: l_car_win implies not l_car_loss and not l_cash_win and not l_goat_loss end
check consistent_cash_win: l_cash_win implies not l_car_win and not l_goat_loss end
check consistent_goat_avoidance: l_goat_avoided implies (l_car_win or l_cash_win) and not l_goat_loss end
check consistent_car_loss: l_car_loss implies l_cash_win or l_goat_loss end
if l_car_win then car_win_count := car_win_count + 1 end
if l_cash_win then cash_win_count := cash_win_count + 1 end
if l_goat_loss then goat_loss_count := goat_loss_count + 1 end
if l_car_loss then car_loss_count := car_loss_count + 1 end
if l_goat_avoided then goat_avoidance_count := goat_avoidance_count + 1 end
if live_contestant.switches_door then
switch_count := switch_count + 1
if l_car_win then
switch_win_count := switch_win_count + 1
end
else -- if not live_contestant.takes_cash and not live_contestant.switches_door then
no_switch_count := no_switch_count + 1
if l_car_win or l_cash_win then
no_switch_win_count := no_switch_win_count + 1
end
end
game_count := game_count + 1
end
print ("%NCar Wins:%T%T " + car_win_count.out +
"%NCash Wins:%T%T " + cash_win_count.out +
"%NGoat Losses:%T%T " + goat_loss_count.out +
"%N-----------------------------" +
"%NTotal Win/Loss:%T%T" + (car_win_count + cash_win_count + goat_loss_count).out +
"%N%N" +
"%NCar Losses:%T%T " + car_loss_count.out +
"%NGoats Avoided:%T%T " + goat_avoidance_count.out +
"%N-----------------------------" +
"%NTotal Loss/Avoid:%T" + (car_loss_count + goat_avoidance_count).out +
"%N-----------------------------" +
"%NStaying Count/Win:%T" + no_switch_count.out + "/" + no_switch_win_count.out + " = " + (no_switch_win_count / no_switch_count * 100).out + " %%" +
"%NSwitch Count/Win:%T" + switch_count.out + "/" + switch_win_count.out + " = " + (switch_win_count / switch_count * 100).out + " %%"
)
end
feature {NONE} -- Implementation: Random Numbers
last_random: like random_number_anchor
-- The last random number chosen.
random_true_or_false: BOOLEAN
-- A randome True or False
do
Result := new_random_of (2) = 2
end
new_random_of (a_number: like random_number_anchor): like door_number_anchor
-- A random number from 1 to `a_number'.
do
Result := (new_random \\ a_number + 1).as_natural_8
end
new_random: like random_number_anchor
-- Random integer
-- Each call returns another random number.
do
random_sequence.forth
Result := random_sequence.item
last_random := Result
ensure
old_random_not_new: old last_random /= last_random
end
random_sequence: RANDOM
-- Random sequence seeded from clock when called.
attribute
create Result.set_seed ((create {TIME}.make_now).milli_second)
end
feature {NONE} -- Implementation: Constants
times_to_play: NATURAL_16 = 1000
-- Times to play the game.
prize: STRING = "Car"
-- Name of the prize
gag_gift: STRING = "Goat"
-- Name of the gag gift
door_anchor: detachable TUPLE [number: like door_number_anchor; name: STRING; is_goat, is_open: BOOLEAN]
-- Type anchor for door tuples.
door_number_anchor: NATURAL_8
-- Type anchor for door numbers.
random_number_anchor: INTEGER
-- Type anchor for random numbers.
counter_anchor: NATURAL_16
-- Type anchor for counters.
feature {NONE} -- Implementation: Contract Support
between_1_and_x_inclusive (a_number, a_value: like door_number_anchor): BOOLEAN
-- Is `a_value' between 1 and `a_number'?
do
Result := (a_value > 0) and (a_value <= a_number)
end
end

View file

@ -0,0 +1,17 @@
(defun montyhall (keep)
(let
((prize (random 3))
(choice (random 3)))
(if keep (= prize choice)
(/= prize choice))))
(let ((cnt 0))
(dotimes (i 10000)
(and (montyhall t) (setq cnt (1+ cnt))))
(princ (format "Strategy keep: %.3f %%" (/ cnt 100.0))))
(let ((cnt 0))
(dotimes (i 10000)
(and (montyhall nil) (setq cnt (1+ cnt))))
(princ (format "Strategy switch: %.3f %%" (/ cnt 100.0))))

View file

@ -0,0 +1,20 @@
integer switchWins, stayWins
switchWins = 0
stayWins = 0
integer winner, choice, shown
for plays = 1 to 10000 do
winner = rand(3)
choice = rand(3)
while 1 do
shown = rand(3)
if shown != winner and shown != choice then
exit
end if
end while
stayWins += choice = winner
switchWins += 6-choice-shown = winner
end for
printf(1, "Switching wins %d times\n", switchWins)
printf(1, "Staying wins %d times\n", stayWins)

View file

@ -0,0 +1,17 @@
include random.fs
variable stay-wins
variable switch-wins
: trial ( -- )
3 random 3 random ( prize choice )
= if 1 stay-wins +!
else 1 switch-wins +!
then ;
: trials ( n -- )
0 stay-wins ! 0 switch-wins !
dup 0 do trial loop
cr stay-wins @ . [char] / emit dup . ." staying wins"
cr switch-wins @ . [char] / emit . ." switching wins" ;
1000 trials

View file

@ -0,0 +1,14 @@
0 value stay-wins
0 value switch-wins
: trial ( -- )
3 choose 3 choose ( -- prize choice )
= IF 1 +TO stay-wins exit ENDIF
1 +TO switch-wins ;
: trials ( n -- )
CLEAR stay-wins
CLEAR switch-wins
dup 0 ?DO trial LOOP
CR stay-wins DEC. ." / " dup DEC. ." staying wins,"
CR switch-wins DEC. ." / " DEC. ." switching wins." ;

View file

@ -0,0 +1,46 @@
PROGRAM MONTYHALL
IMPLICIT NONE
INTEGER, PARAMETER :: trials = 10000
INTEGER :: i, choice, prize, remaining, show, staycount = 0, switchcount = 0
LOGICAL :: door(3)
REAL :: rnum
CALL RANDOM_SEED
DO i = 1, trials
door = .FALSE.
CALL RANDOM_NUMBER(rnum)
prize = INT(3*rnum) + 1
door(prize) = .TRUE. ! place car behind random door
CALL RANDOM_NUMBER(rnum)
choice = INT(3*rnum) + 1 ! choose a door
DO
CALL RANDOM_NUMBER(rnum)
show = INT(3*rnum) + 1
IF (show /= choice .AND. show /= prize) EXIT ! Reveal a goat
END DO
SELECT CASE(choice+show) ! Calculate remaining door index
CASE(3)
remaining = 3
CASE(4)
remaining = 2
CASE(5)
remaining = 1
END SELECT
IF (door(choice)) THEN ! You win by staying with your original choice
staycount = staycount + 1
ELSE IF (door(remaining)) THEN ! You win by switching to other door
switchcount = switchcount + 1
END IF
END DO
WRITE(*, "(A,F6.2,A)") "Chance of winning by not switching is", real(staycount)/trials*100, "%"
WRITE(*, "(A,F6.2,A)") "Chance of winning by switching is", real(switchcount)/trials*100, "%"
END PROGRAM MONTYHALL

View file

@ -0,0 +1,63 @@
package main
import (
"fmt"
"math/rand"
)
func main() {
games := 1000000
var switchWinsCar, keepWinsCar int
for i := 0; i < games; i++ {
// simulate game
carDoor := rand.Intn(3)
firstChoice := rand.Intn(3)
var hostOpens int
if carDoor == firstChoice {
hostOpens = rand.Intn(2)
if hostOpens >= carDoor {
hostOpens++
}
} else {
hostOpens = 3 - carDoor - firstChoice
}
remainingDoor := 3 - hostOpens - firstChoice
// some assertions that above code produced a valid game state
if carDoor < 0 || carDoor > 2 {
panic("car behind invalid door")
}
if firstChoice < 0 || firstChoice > 2 {
panic("contestant chose invalid door")
}
if hostOpens < 0 || hostOpens > 2 {
panic("host opened invalid door")
}
if hostOpens == carDoor {
panic("host opened door with car")
}
if hostOpens == firstChoice {
panic("host opened contestant's first choice")
}
if remainingDoor < 0 || remainingDoor > 2 {
panic("remaining door invalid")
}
if remainingDoor == firstChoice {
panic("remaining door same as contestant's first choice")
}
if remainingDoor == hostOpens {
panic("remaining door same as one host opened")
}
// tally results
if firstChoice == carDoor {
keepWinsCar++
}
if remainingDoor == carDoor {
switchWinsCar++
}
}
fmt.Println("In", games, "games,")
fmt.Println("switching doors won the car", switchWinsCar, "times,")
fmt.Println("keeping same door won the car", keepWinsCar, "times.")
}

View file

@ -0,0 +1,34 @@
import System.Random (StdGen, getStdGen, randomR)
trials :: Int
trials = 10000
data Door = Car | Goat deriving Eq
play :: Bool -> StdGen -> (Door, StdGen)
play switch g = (prize, new_g)
where (n, new_g) = randomR (0, 2) g
d1 = [Car, Goat, Goat] !! n
prize = case switch of
False -> d1
True -> case d1 of
Car -> Goat
Goat -> Car
cars :: Int -> Bool -> StdGen -> (Int, StdGen)
cars n switch g = f n (0, g)
where f 0 (cs, g) = (cs, g)
f n (cs, g) = f (n - 1) (cs + result, new_g)
where result = case prize of Car -> 1; Goat -> 0
(prize, new_g) = play switch g
main = do
g <- getStdGen
let (switch, g2) = cars trials True g
(stay, _) = cars trials False g2
putStrLn $ msg "switch" switch
putStrLn $ msg "stay" stay
where msg strat n = "The " ++ strat ++ " strategy succeeds " ++
percent n ++ "% of the time."
percent n = show $ round $
100 * (fromIntegral n) / (fromIntegral trials)

View file

@ -0,0 +1,21 @@
import Control.Monad.State
play :: Bool -> State StdGen Door
play switch = do
i <- rand
let d1 = [Car, Goat, Goat] !! i
return $ case switch of
False -> d1
True -> case d1 of
Car -> Goat
Goat -> Car
where rand = do
g <- get
let (v, new_g) = randomR (0, 2) g
put new_g
return v
cars :: Int -> Bool -> StdGen -> (Int, StdGen)
cars n switch g = (numcars, new_g)
where numcars = length $ filter (== Car) prize_list
(prize_list, new_g) = runState (replicateM n (play switch)) g

View file

@ -0,0 +1,2 @@
The switch strategy succeeds 67% of the time.
The stay strategy succeeds 34% of the time.

View file

@ -0,0 +1,32 @@
REAL :: ndoors=3, doors(ndoors), plays=1E4
DLG(NameEdit = plays, DNum=1, Button='Go')
switchWins = 0
stayWins = 0
DO play = 1, plays
doors = 0 ! clear the doors
winner = 1 + INT(RAN(ndoors)) ! door that has the prize
doors(winner) = 1
guess = 1 + INT(RAN(doors)) ! player chooses his door
IF( guess == winner ) THEN ! Monty decides which door to open:
show = 1 + INT(RAN(2)) ! select 1st or 2nd goat-door
checked = 0
DO check = 1, ndoors
checked = checked + (doors(check) == 0)
IF(checked == show) open = check
ENDDO
ELSE
open = (1+2+3) - winner - guess
ENDIF
new_guess_if_switch = (1+2+3) - guess - open
stayWins = stayWins + doors(guess) ! count if guess was correct
switchWins = switchWins + doors(new_guess_if_switch)
ENDDO
WRITE(ClipBoard, Name) plays, switchWins, stayWins
END

View file

@ -0,0 +1,4 @@
! plays=1E3; switchWins=695; stayWins=305;
! plays=1E4; switchWins=6673; stayWins=3327;
! plays=1E5; switchWins=66811; stayWins=33189;
! plays=1E6; switchWins=667167; stayWins=332833;

View file

@ -0,0 +1,19 @@
procedure main(arglist)
rounds := integer(arglist[1]) | 10000
doors := '123'
strategy1 := strategy2 := 0
every 1 to rounds do {
goats := doors -- ( car := ?doors )
guess1 := ?doors
show := goats -- guess1
if guess1 == car then strategy1 +:= 1
else strategy2 +:= 1
}
write("Monty Hall simulation for ", rounds, " rounds.")
write("Strategy 1 'Staying' won ", real(strategy1) / rounds )
write("Strategy 2 'Switching' won ", real(strategy2) / rounds )
end

View file

@ -0,0 +1 @@
pick=: {~ ?@#

View file

@ -0,0 +1 @@
DOORS=:1 2 3

View file

@ -0,0 +1 @@
scenario=: ((pick@-.,])pick,pick) bind DOORS

View file

@ -0,0 +1 @@
stayWin=: =/@}.

View file

@ -0,0 +1 @@
switchWin=: pick@(DOORS -. }:) = {:

View file

@ -0,0 +1,2 @@
+/ (stayWin,switchWin)@scenario"0 i.1000
320 680

View file

@ -0,0 +1,11 @@
simulate=:3 :0
1 2 3 simulate y
:
pick=. {~ ?@#
scenario=. ((pick@-.,])pick,pick) bind x
stayWin=. =/@}.
switchWin=. pick@(x -. }:) = {:
r=.(stayWin,switchWin)@scenario"0 i.1000
labels=. ];.2 'limit stay switch '
smoutput labels,.":"0 y,+/r
)

View file

@ -0,0 +1,4 @@
simulate 1000
limit 1000
stay 304
switch 696

View file

@ -0,0 +1,4 @@
1 2 3 4 simulate 1000
limit 1000
stay 233
switch 388

View file

@ -0,0 +1,25 @@
import java.util.Random;
public class Monty{
public static void main(String[] args){
int switchWins = 0;
int stayWins = 0;
Random gen = new Random();
for(int plays = 0;plays < 32768;plays++ ){
int[] doors = {0,0,0};//0 is a goat, 1 is a car
doors[gen.nextInt(3)] = 1;//put a winner in a random door
int choice = gen.nextInt(3); //pick a door, any door
int shown; //the shown door
do{
shown = gen.nextInt(3);
//don't show the winner or the choice
}while(doors[shown] == 1 || shown == choice);
stayWins += doors[choice];//if you won by staying, count it
//the switched (last remaining) door is (3 - choice - shown), because 0+1+2=3
switchWins += doors[3 - choice - shown];
}
System.out.println("Switching wins " + switchWins + " times.");
System.out.println("Staying wins " + stayWins + " times.");
}
}

View file

@ -0,0 +1,38 @@
function montyhall(tests, doors) {
'use strict';
tests = tests ? tests : 1000;
doors = doors ? doors : 3;
var prizeDoor, chosenDoor, shownDoor, switchDoor, chosenWins = 0, switchWins = 0;
// randomly pick a door excluding input doors
function pick(excludeA, excludeB) {
var door;
do {
door = Math.floor(Math.random() * doors);
} while (door === excludeA || door === excludeB);
return door;
}
// run tests
for (var i = 0; i < tests; i ++) {
// pick set of doors
prizeDoor = pick();
chosenDoor = pick();
shownDoor = pick(prizeDoor, chosenDoor);
switchDoor = pick(chosenDoor, shownDoor);
// test set for both choices
if (chosenDoor === prizeDoor) {
chosenWins ++;
} else if (switchDoor === prizeDoor) {
switchWins ++;
}
}
// results
return {
stayWins: chosenWins + ' ' + (100 * chosenWins / tests) + '%',
switchWins: switchWins + ' ' + (100 * switchWins / tests) + '%'
};
}

View file

@ -0,0 +1,6 @@
montyhall(1000, 3)
Object {stayWins: "349 34.9%", switchWins: "651 65.1%"}
montyhall(1000, 4)
Object {stayWins: "253 25.3%", switchWins: "384 38.4%"}
montyhall(1000, 5)
Object {stayWins: "202 20.2%", switchWins: "265 26.5%"}

View file

@ -0,0 +1,44 @@
var totalGames = 10000,
selectDoor = function () {
return Math.floor(Math.random() * 3); // Choose a number from 0, 1 and 2.
},
games = (function () {
var i = 0, games = [];
for (; i < totalGames; ++i) {
games.push(selectDoor()); // Pick a door which will hide the prize.
}
return games;
}()),
play = function (switchDoor) {
var i = 0, j = games.length, winningDoor, randomGuess, totalTimesWon = 0;
for (; i < j; ++i) {
winningDoor = games[i];
randomGuess = selectDoor();
if ((randomGuess === winningDoor && !switchDoor) ||
(randomGuess !== winningDoor && switchDoor))
{
/*
* If I initially guessed the winning door and didn't switch,
* or if I initially guessed a losing door but then switched,
* I've won.
*
* The only time I lose is when I initially guess the winning door
* and then switch.
*/
totalTimesWon++;
}
}
return totalTimesWon;
};
/*
* Start the simulation
*/
console.log("Playing " + totalGames + " games");
console.log("Wins when not switching door", play(false));
console.log("Wins when switching door", play(true));

View file

@ -0,0 +1,3 @@
Playing 10000 games
Wins when not switching door 3326
Wins when switching door 6630

View file

@ -0,0 +1,25 @@
'adapted from BASIC solution
DIM doors(3) '0 is a goat, 1 is a car
total = 10000 'set desired number of iterations
switchWins = 0
stayWins = 0
FOR plays = 1 TO total
winner = INT(RND(1) * 3) + 1
doors(winner) = 1'put a winner in a random door
choice = INT(RND(1) * 3) + 1'pick a door, any door
DO
shown = INT(RND(1) * 3) + 1
'don't show the winner or the choice
LOOP WHILE doors(shown) = 1 OR shown = choice
if doors(choice) = 1 then
stayWins = stayWins + 1 'if you won by staying, count it
else
switchWins = switchWins + 1'could have switched to win
end if
doors(winner) = 0 'clear the doors for the next test
NEXT
PRINT "Result for ";total;" games."
PRINT "Switching wins "; switchWins; " times."
PRINT "Staying wins "; stayWins; " times."

View file

@ -0,0 +1,17 @@
function playgame(player)
local car = math.random(3)
local pchoice = player.choice()
local function neither(a, b) --slow, but it works
local el = math.random(3)
return (el ~= a and el ~= b) and el or neither(a, b)
end
local el = neither(car, pchoice)
if(player.switch) then pchoice = neither(pchoice, el) end
player.wins = player.wins + (pchoice == car and 1 or 0)
end
for _, v in ipairs{true, false} do
player = {choice = function() return math.random(3) end,
wins = 0, switch = v}
for i = 1, 20000 do playgame(player) end
print(player.wins)
end

View file

@ -0,0 +1,56 @@
function montyHall(numDoors,numSimulations)
assert(numDoors > 2);
function num = randInt(n)
num = floor( n*rand()+1 );
end
%The first column will tallie wins, the second losses
switchedDoors = [0 0];
stayed = [0 0];
for i = (1:numSimulations)
availableDoors = (1:numDoors); %Preallocate the available doors
winningDoor = randInt(numDoors); %Define the winning door
playersOriginalChoice = randInt(numDoors); %The player picks his initial choice
availableDoors(playersOriginalChoice) = []; %Remove the players choice from the available doors
%Pick the door to open from the available doors
openDoor = availableDoors(randperm(numel(availableDoors))); %Sort the available doors randomly
openDoor(openDoor == winningDoor) = []; %Make sure Monty doesn't open the winning door
openDoor = openDoor(randInt(numel(openDoor))); %Choose a random door to open
availableDoors(availableDoors==openDoor) = []; %Remove the open door from the available doors
availableDoors(end+1) = playersOriginalChoice; %Put the player's original choice back into the pool of available doors
availableDoors = sort(availableDoors);
playersNewChoice = availableDoors(randInt(numel(availableDoors))); %Pick one of the available doors
if playersNewChoice == playersOriginalChoice
switch playersNewChoice == winningDoor
case true
stayed(1) = stayed(1) + 1;
case false
stayed(2) = stayed(2) + 1;
otherwise
error 'ERROR'
end
else
switch playersNewChoice == winningDoor
case true
switchedDoors(1) = switchedDoors(1) + 1;
case false
switchedDoors(2) = switchedDoors(2) + 1;
otherwise
error 'ERROR'
end
end
end
disp(sprintf('Switch win percentage: %f%%\nStay win percentage: %f%%\n', [switchedDoors(1)/sum(switchedDoors),stayed(1)/sum(stayed)] * 100));
end

View file

@ -0,0 +1,3 @@
>> montyHall(3,100000)
Switch win percentage: 66.705972%
Stay win percentage: 33.420062%

View file

@ -0,0 +1,25 @@
fn montyHall choice switch =
(
doors = #(false, false, false)
doors[random 1 3] = true
chosen = doors[choice]
if switch then chosen = not chosen
chosen
)
fn iterate iterations switched =
(
wins = 0
for i in 1 to iterations do
(
if (montyHall (random 1 3) switched) then
(
wins += 1
)
)
wins * 100 / iterations as float
)
iterations = 10000
format ("Stay strategy:%\%\n") (iterate iterations false)
format ("Switch strategy:%\%\n") (iterate iterations true)

View file

@ -0,0 +1,2 @@
Stay strategy:33.77%
Switch strategy:66.84%

View file

@ -0,0 +1,10 @@
montyHall[nGames_] :=
Module[{r, winningDoors, firstChoices, nStayWins, nSwitchWins, s},
r := RandomInteger[{1, 3}, nGames];
winningDoors = r;
firstChoices = r;
nStayWins = Count[Transpose[{winningDoors, firstChoices}], {d_, d_}];
nSwitchWins = nGames - nStayWins;
Grid[{{"Strategy", "Wins", "Win %"}, {"Stay", Row[{nStayWins, "/", nGames}], s=N[100 nStayWins/nGames]},
{"Switch", Row[{nSwitchWins, "/", nGames}], 100 - s}}, Frame -> All]]

View file

@ -0,0 +1 @@
montyHall[100000]

View file

@ -0,0 +1,27 @@
<?php
function montyhall($iterations){
$switch_win = 0;
$stay_win = 0;
foreach (range(1, $iterations) as $i){
$doors = array(0, 0, 0);
$doors[array_rand($doors)] = 1;
$choice = array_rand($doors);
do {
$shown = array_rand($doors);
} while($shown == $choice || $doors[$shown] == 1);
$stay_win += $doors[$choice];
$switch_win += $doors[3 - $choice - $shown];
}
$stay_percentages = ($stay_win/$iterations)*100;
$switch_percentages = ($switch_win/$iterations)*100;
echo "Iterations: {$iterations} - ";
echo "Stayed wins: {$stay_win} ({$stay_percentages}%) - ";
echo "Switched wins: {$switch_win} ({$switch_percentages}%)";
}
montyhall(10000);
?>

View file

@ -0,0 +1,27 @@
#! /usr/bin/perl
use strict;
my $trials = 10000;
my $stay = 0;
my $switch = 0;
foreach (1 .. $trials)
{
my $prize = int(rand 3);
# let monty randomly choose a door where he puts the prize
my $chosen = int(rand 3);
# let us randomly choose a door...
my $show;
do { $show = int(rand 3) } while $show == $chosen || $show == $prize;
# ^ monty opens a door which is not the one with the
# prize, that he knows it is the one the player chosen
$stay++ if $prize == $chosen;
# ^ if player chose the correct door, player wins only if he stays
$switch++ if $prize == 3 - $chosen - $show;
# ^ if player switches, the door he picks is (3 - $chosen - $show),
# because 0+1+2=3, and he picks the only remaining door that is
# neither $chosen nor $show
}
print "Stay win ratio " . (100.0 * $stay/$trials) . "\n";
print "Switch win ratio " . (100.0 * $switch/$trials) . "\n";

View file

@ -0,0 +1,19 @@
(de montyHall (Keep)
(let (Prize (rand 1 3) Choice (rand 1 3))
(if Keep # Keeping the first choice?
(= Prize Choice) # Yes: Monty's choice doesn't matter
(<> Prize Choice) ) ) ) # Else: Win if your first choice was wrong
(prinl
"Strategy KEEP -> "
(let Cnt 0
(do 10000 (and (montyHall T) (inc 'Cnt)))
(format Cnt 2) )
" %" )
(prinl
"Strategy SWITCH -> "
(let Cnt 0
(do 10000 (and (montyHall NIL) (inc 'Cnt)))
(format Cnt 2) )
" %" )

View file

@ -0,0 +1,45 @@
'''
I could understand the explanation of the Monty Hall problem
but needed some more evidence
References:
http://www.bbc.co.uk/dna/h2g2/A1054306
http://en.wikipedia.org/wiki/Monty_Hall_problem especially:
http://en.wikipedia.org/wiki/Monty_Hall_problem#Increasing_the_number_of_doors
'''
from random import randrange
doors, iterations = 3,100000 # could try 100,1000
def monty_hall(choice, switch=False, doorCount=doors):
# Set up doors
door = [False]*doorCount
# One door with prize
door[randrange(doorCount)] = True
chosen = door[choice]
unpicked = door
del unpicked[choice]
# Out of those unpicked, the alternative is either:
# the prize door, or
# an empty door if the initial choice is actually the prize.
alternative = True in unpicked
if switch:
return alternative
else:
return chosen
print "\nMonty Hall problem simulation:"
print doors, "doors,", iterations, "iterations.\n"
print "Not switching allows you to win",
print sum(monty_hall(randrange(3), switch=False)
for x in range(iterations)),
print "out of", iterations, "times."
print "Switching allows you to win",
print sum(monty_hall(randrange(3), switch=True)
for x in range(iterations)),
print "out of", iterations, "times.\n"

View file

@ -0,0 +1,62 @@
# Since R is a vector based language that penalizes for loops, we will avoid
# for-loops, instead using "apply" statement variants (like "map" in other
# functional languages).
set.seed(19771025) # set the seed to set the same results as this code
N <- 10000 # trials
true_answers <- sample(1:3, N, replace=TRUE)
# We can assme that the contestant always choose door 1 without any loss of
# generality, by equivalence. That is, we can always relabel the doors
# to make the user-chosen door into door 1.
# Thus, the host opens door '2' unless door 2 has the prize, in which case
# the host opens door 3.
host_opens <- 2 + (true_answers == 2)
other_door <- 2 + (true_answers != 2)
## if always switch
summary( other_door == true_answers )
## if we never switch
summary( true_answers == 1)
## if we randomly switch
random_switch <- other_door
random_switch[runif(N) >= .5] <- 1
summary(random_switch == true_answers)
## To go with the exact parameters of the Rosetta challenge, complicating matters....
## Note that the player may initially choose any of the three doors (not just Door 1),
## that the host opens a different door revealing a goat (not necessarily Door 3), and
## that he gives the player a second choice between the two remaining unopened doors.
N <- 10000 #trials
true_answers <- sample(1:3, N, replace=TRUE)
user_choice <- sample(1:3, N, replace=TRUE)
## the host_choice is more complicated
host_chooser <- function(user_prize) {
# this could be cleaner
bad_choices <- unique(user_prize)
# in R, the x[-vector] form implies, choose the indices in x not in vector
choices <- c(1:3)[-bad_choices]
# if the first arg to sample is an int, it treats it as the number of choices
if (length(choices) == 1) { return(choices)}
else { return(sample(choices,1))}
}
host_choice <- apply( X=cbind(true_answers,user_choice), FUN=host_chooser,MARGIN=1)
not_door <- function(x){ return( (1:3)[-x]) } # we could also define this
# directly at the FUN argument following
other_door <- apply( X = cbind(user_choice,host_choice), FUN=not_door, MARGIN=1)
## if always switch
summary( other_door == true_answers )
## if we never switch
summary( true_answers == user_choice)
## if we randomly switch
random_switch <- user_choice
change <- runif(N) >= .5
random_switch[change] <- other_door[change]
summary(random_switch == true_answers)

View file

@ -0,0 +1,26 @@
n = 10_000 #number of times to play
stay = switch = 0 #sum of each strategy's wins
n.times do #play the game n times
#the doors reveal 2 goats and a car
doors = [ :goat , :goat , :goat ]
doors[rand(3)] = :car
#random guess
guess = rand(3)
#random door shown, but it is neither the guess nor the car
begin shown = rand(3) end while shown == guess || doors[shown] == :car
#staying with the initial guess wins if the initial guess is the car
stay += 1 if doors[guess] == :car
#switching guesses wins if the unshown door is the car
switch += 1 if doors[3-guess-shown] == :car
end
puts "Staying wins %.2f%% of the time." % (100.0 * stay / n)
puts "Switching wins %.2f%% of the time." % (100.0 * switch / n)

View file

@ -0,0 +1,33 @@
import scala.util.Random
object MontyHallSimulation {
def main(args: Array[String]) {
val samples = if (args.size == 1 && (args(0) matches "\\d+")) args(0).toInt else 1000
val doors = Set(0, 1, 2)
var stayStrategyWins = 0
var switchStrategyWins = 0
1 to samples foreach { _ =>
val prizeDoor = Random shuffle doors head;
val choosenDoor = Random shuffle doors head;
val hostDoor = Random shuffle (doors - choosenDoor - prizeDoor) head;
val switchDoor = doors - choosenDoor - hostDoor head;
(choosenDoor, switchDoor) match {
case (`prizeDoor`, _) => stayStrategyWins += 1
case (_, `prizeDoor`) => switchStrategyWins += 1
}
}
def percent(n: Int) = n * 100 / samples
val report = """|%d simulations were ran.
|Staying won %d times (%d %%)
|Switching won %d times (%d %%)""".stripMargin
println(report
format (samples,
stayStrategyWins, percent(stayStrategyWins),
switchStrategyWins, percent(switchStrategyWins)))
}
}

View file

@ -0,0 +1,70 @@
(define (random-from-list list) (list-ref list (random (length list))))
(define (random-permutation list)
(if (null? list)
'()
(let* ((car (random-from-list list))
(cdr (random-permutation (remove car list))))
(cons car cdr))))
(define (random-configuration) (random-permutation '(goat goat car)))
(define (random-door) (random-from-list '(0 1 2)))
(define (trial strategy)
(define (door-with-goat-other-than door strategy)
(cond ((and (not (= 0 door)) (equal? (list-ref strategy 0) 'goat)) 0)
((and (not (= 1 door)) (equal? (list-ref strategy 1) 'goat)) 1)
((and (not (= 2 door)) (equal? (list-ref strategy 2) 'goat)) 2)))
(let* ((configuration (random-configuration))
(players-first-guess (strategy `(would-you-please-pick-a-door?)))
(door-to-show-player (door-with-goat-other-than players-first-guess
configuration))
(players-final-guess (strategy `(there-is-a-goat-at/would-you-like-to-move?
,players-first-guess
,door-to-show-player))))
(if (equal? (list-ref configuration players-final-guess) 'car)
'you-win!
'you-lost)))
(define (stay-strategy message)
(case (car message)
((would-you-please-pick-a-door?) (random-door))
((there-is-a-goat-at/would-you-like-to-move?)
(let ((first-choice (cadr message)))
first-choice))))
(define (switch-strategy message)
(case (car message)
((would-you-please-pick-a-door?) (random-door))
((there-is-a-goat-at/would-you-like-to-move?)
(let ((first-choice (cadr message))
(shown-goat (caddr message)))
(car (remove first-choice (remove shown-goat '(0 1 2))))))))
(define-syntax repeat
(syntax-rules ()
((repeat <n> <body> ...)
(let loop ((i <n>))
(if (zero? i)
'()
(cons ((lambda () <body> ...))
(loop (- i 1))))))))
(define (count element list)
(if (null? list)
0
(if (equal? element (car list))
(+ 1 (count element (cdr list)))
(count element (cdr list)))))
(define (prepare-result strategy results)
`(,strategy won with probability
,(exact->inexact (* 100 (/ (count 'you-win! results) (length results)))) %))
(define (compare-strategies times)
(append
(prepare-result 'stay-strategy (repeat times (trial stay-strategy)))
'(and)
(prepare-result 'switch-strategy (repeat times (trial switch-strategy)))))
;; > (compare-strategies 1000000)
;; (stay-strategy won with probability 33.3638 %
;; and switch-strategy won with probability 66.716 %)

View file

@ -0,0 +1,10 @@
set stay 0; set change 0; set total 10000
for {set i 0} {$i<$total} {incr i} {
if {int(rand()*3) == int(rand()*3)} {
incr stay
} else {
incr change
}
}
puts "Estimate: $stay/$total wins for staying strategy"
puts "Estimate: $change/$total wins for changing strategy"

View file

@ -0,0 +1,66 @@
package require Tcl 8.5
# Utility: pick a random item from a list
proc pick list {
lindex $list [expr {int(rand()*[llength $list])}]
}
# Utility: remove an item from a list if it is there
proc remove {list item} {
set idx [lsearch -exact $list $item]
return [lreplace $list $idx $idx]
}
# Codify how Monty will present the new set of doors to choose between
proc MontyHallAction {doors car picked} {
set unpicked [remove $doors $picked]
if {$car in $unpicked} {
# Remove a random unpicked door without the car behind it
set carless [remove $unpicked $car]
return [list {*}[remove $carless [pick $carless]] $car]
# Expressed this way so Monty Hall isn't theoretically
# restricted to using 3 doors, though that could be written
# as just: return [list $car]
} else {
# Monty has a real choice now...
return [remove $unpicked [pick $unpicked]]
}
}
# The different strategies you might choose
proc Strategy:Stay {originalPick otherChoices} {
return $originalPick
}
proc Strategy:Change {originalPick otherChoices} {
return [pick $otherChoices]
}
proc Strategy:PickAnew {originalPick otherChoices} {
return [pick [list $originalPick {*}$otherChoices]]
}
# Codify one round of the game
proc MontyHallGameRound {doors strategy winCounter} {
upvar 1 $winCounter wins
set car [pick $doors]
set picked [pick $doors]
set newDoors [MontyHallAction $doors $car $picked]
set picked [$strategy $picked $newDoors]
# Check for win...
if {$car eq $picked} {
incr wins
}
}
# We're always using three doors
set threeDoors {a b c}
set stay 0; set change 0; set anew 0
set total 10000
# Simulate each of the different strategies
for {set i 0} {$i<$total} {incr i} {
MontyHallGameRound $threeDoors Strategy:Stay stay
MontyHallGameRound $threeDoors Strategy:Change change
MontyHallGameRound $threeDoors Strategy:PickAnew anew
}
# Print the results
puts "Estimate: $stay/$total wins for 'staying' strategy"
puts "Estimate: $change/$total wins for 'changing' strategy"
puts "Estimate: $anew/$total wins for 'picking anew' strategy"