Algorithm Implementation/Simulation/Monty Hall problem
PHP
editclass MontyHall {
private $rounds = 10;
private $doors = 3;
private $wins = array( "changing" => 0, "keeping" => 0 );
public function setDoors( $doors )
{
$this->doors = $doors;
return $this;
}
public function play( $rounds = false )
{
if ( $rounds ) $this->rounds = $rounds;
for ( $i = 0; $i < $this->rounds; $i++ ) {
$prizeDoor = $this->randomDoor();
$playerChoiseDoor = $this->randomDoor();
$hostOpenDoor = $this->chooseDoor( $prizeDoor, $playerChoiseDoor );
$playerChangeDoor = $this->chooseDoor( $playerChoiseDoor, $hostOpenDoor );
if( $playerChoiseDoor == $prizeDoor ) $this->wins["keeping"]++;
if( $playerChangeDoor == $prizeDoor ) $this->wins["changing"]++;
}
return $this;
}
public function getResults()
{
echo " Winnings: " . "<br>" .
" - Changing the door: " . ( $this->wins["changing"] * 100 ) / $this->rounds . "%<br>" .
" - Not Changing the door: " . ( $this->wins["keeping"] * 100 ) / $this->rounds . "%<br>" .
" Simulation Statistics: " . "<br>" .
" - Games played: " . $this->rounds . "<br>" .
" - Doors used: " . $this->doors . "<br>" ;
}
private function randomDoor()
{
return rand( 1, $this->doors );
}
private function chooseDoor( $number1 = null, $number2 = null )
{
do $result = $this->randomDoor();
while ( $result == $number1 OR $result == $number2 );
return $result;
}
}
// Use the MontyHall Simulation
$montyhall = new MontyHall();
$montyhall->setDoors(3)->play(10000)->getResults();
Javascript
editArray.prototype.remove = function(i) {
this.splice(i, 1);
};
SimulationEngine = function(){
}
SimulationEngine.prototype = {
simulate: function(maxSim){
if(!maxSim || maxSim < 0)
maxSim = 1000;
var winSwitching = 0;
var loseSwitching = 0;
var carCard = 0;
var goat = 1;
function userPickOne(cards){
var index = Math.floor(Math.random()*11)%3;
cards.remove(index);
}
function hostDiscardOne(cards){
if(cards[0] === goat)
cards.remove(0);
else
cards.remove(1);
}
function updateStatus(cards){
if(cards[0] === carCard)
winSwitching++;
else
loseSwitching++;
}
for(var sim = 0; sim < maxSim; sim++){
var cards = [carCard,goat,goat];
userPickOne(cards);
hostDiscardOne(cards);
updateStatus(cards);
}
return {
winSwitching: winSwitching,
loseSwitching: loseSwitching
}
}
}
function simulate(){
var maxSim = 10000;
var engine = new SimulationEngine();
var result = engine.simulate(maxSim);
var strResult = "Total simulations are " + maxSim +
", WIN by switching = " + result.winSwitching * 100 / maxSim +
", LOST by switching = " + result.loseSwitching * 100 / maxSim;
alert(strResult);
}
Java
editimport java.util.Random;
public class MontyHall {
public static final Random gen = new Random();
public static final int ROUNDS = 10000;
/** chooses a random door other than door1 or door2 */
private static int chooseAnotherDoor(int door1, int door2) {
int result;
do
result = gen.nextInt(3);
while (result == door1 || result == door2);
return result;
}
public static void main(String[] args) {
System.out.println("begin playing " + ROUNDS + " rounds");
int wins = 0;
for (int i = 0; i < ROUNDS; i++) {
int prize = gen.nextInt(3);
int userChoice1 = gen.nextInt(3);
// host opens door other than user's choice without prize
int hostChoice = chooseAnotherDoor(prize, userChoice1);
// user always switches
int userChoice2 = chooseAnotherDoor(userChoice1, hostChoice);
if (userChoice2 == prize)
wins++;
}
System.out.println(wins + " wins by switching");
}
}
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
srand(time(NULL));
random_device rd;
mt19937 gen{ rd() };
unsigned long long stay = 0;
unsigned long long change = 0;
while(true)
{
vector<bool> boxes(3, false);
boxes[0] = true; // Place a car
shuffle(boxes.begin(), boxes.end(), gen);
if(boxes[rand() % 3])
{
stay++;
cout << "STAY wins\n";
}
else
{
change++;
cout << "CHANGE wins\n";
}
cout << "STAY: " << int((double)stay/(stay + change) * 100 + 0.5) << "%; "
<< "CHANGE: " << int((double)change/(stay + change) * 100 + 0.5) << "%\n" << endl;
}
}
integer swapWins = 0, stayWins = 0, winner, choice, reveal, other
atom t0 = time()
for game=1 to 1_000_000 do
winner = rand(3)
choice = rand(3)
while 1 do
reveal = rand(3)
if reveal!=winner and reveal!=choice then exit end if
end while
stayWins += (choice==winner)
other = 6-choice-reveal -- (as 1+2+3=6, and reveal!=choice)
swapWins += (other==winner)
end for
printf(1, "Stay: %,d\nSwap: %,d\nTime: %3.2fs\n",{stayWins,swapWins,time()-t0})
#!/usr/bin/python
import sys,random
rounds = 10000
wins = 0
random.seed()
# The "-n" commandline option makes us run without ever switching.
if len(sys.argv) > 1 and sys.argv[1] == "-n":
swap = False
else:
swap = True
for i in range(rounds) :
# Generate random door contents
doors = ["goat", "goat", "car"]
random.shuffle(doors)
# Pick a door
door_choice = random.randrange(3)
print("Selecting door", door_choice)
# Show a door with a goat
for j, contents in enumerate(doors):
if j != door_choice and contents == "goat":
goat_door = j
print("The host reveals a goat behind door", goat_door)
break
if swap:
# Swap to the other door
for j, contents in enumerate(doors):
if j != door_choice and j != goat_door:
swap_to = j
print("Swapping to door", swap_to)
else:
swap_to = door_choice
if doors[swap_to] == "car":
wins += 1
print("You won the car!!")
else:
print("Sorry, but you're stuck with a goat")
print("You played", rounds, "rounds, and won", wins, "of them!")
numsim = 100000 doors = 1:3 opendoor = function(x) { if (x[1]==x[2]) return(sample(doors[-c(x[1])], 1)) else return(doors[-c(x[1],x[2])]) } swapdoor = function(x) { return(doors[-c(x[1], x[2])]) } winner = sample(doors, numsim, replace=TRUE) choice = sample(doors, numsim, replace=TRUE) open = apply(cbind(winner, choice), 1, opendoor) newchoice = apply(cbind(open, choice), 1, swapdoor) # cat("without switching, won ", round(sum(winner==choice)/numsim*100,1)," percent of the time.\n", sep="") cat("with switching, won ", round(sum(winner==newchoice)/numsim*100,1)," percent of the time.\n", sep="")
def createDoors
doors = [false, false, false]
doors[rand(3)] = true
doors
end
def openADoorThatHasADonkey(doors, userChoice)
([0, 1, 2] - [userChoice, doors.index(true)]).first
end
def changeUserChoice(choices)
([0, 1, 2] - choices).first
end
def play
doors = createDoors()
userChoice1 = rand(3)
hostChoice = openADoorThatHasADonkey(doors, userChoice1)
userChoice2 = changeUserChoice([userChoice1, hostChoice]) # note: to change
# script so that user DOESN'T change her choice and demonstrate the fallacy
# of that approach, comment the userChoice2 line above and uncomment the
# line below:
# userChoice2 = userChoice1
doors.index(true) == userChoice2
end
games, wins = 10000, 0
games.times { wins += 1 if play() }
print 100*wins/games, " %"
Another implementation
car = wins = 0
many = 100000
many.times do
choice1 = rand(3)
host_opts = [0, 1, 2] - [choice1, car]
choice2 = [0, 1, 2] - [choice1, host_opts.first]
wins += 1 if choice2 == [car]
end
puts "#{(wins * 100) / many}%"
data mh; do i = 1 to 100000; prize = rand("TABLE",.333,.333); * Monty puts the prize behind a random door; initial_guess = rand("TABLE",.333,.333); * We make a random initial guess; * if the initial guess is right, Monte can open either of the others; * which means that player can switch to either of the other doors; if initial_guess eq prize then do; new_guess = initial_guess; * choose a door until it's different from the initial guess—that's the door we switch to; do until (new_guess ne initial_guess); new_guess = rand("TABLE",.333,.333); end; end; * If the initial guess was wrong, Monte can rule out only one of the other doors; * which means that we must switch to the right door; if initial_guess ne prize then new_guess = prize; output; end; run; *; data mh2; set mh; win_by_keep = (initial_guess eq prize); win_by_switch = (new_guess eq prize); run; *; proc means data = mh2 mean; var win_by_keep win_by_switch; run;
Option Explicit
Option Base 1
Sub simulate()
Dim iCount As Long
Dim wins As Long
Dim games As Long
games = 10000000
For iCount = 1 To games
If Play Then wins = wins + 1
Next
MsgBox Round(((wins / games) * 100), 1) & "%"
End Sub
Function Play()
Dim doors() As Boolean
Dim userChoice1 As Integer
Dim hostchoice As Integer
Dim userChoice2 As Integer
doors = createDoors()
userChoice1 = Int(3 * Rnd() + 1)
hostchoice = openADoorThatHasADonkey(doors(), userChoice1)
userChoice2 = changeUserChoice(userChoice1, hostchoice)
Play = doors(userChoice2)
End Function
Function createDoors() As Boolean()
Dim temp(3) As Boolean
temp(1) = False
temp(2) = False
temp(3) = False
temp(Int(3 * Rnd() + 1)) = True
createDoors = temp
End Function
Function openADoorThatHasADonkey(doors() As Boolean, userChoice)
Dim iCount As Integer
Dim temp As Integer
For iCount = 1 To 3
If Not doors(iCount) And userChoice <> iCount Then
temp = iCount
Exit For
End If
Next iCount
openADoorThatHasADonkey = temp
End Function
Function changeUserChoice(userChoice1 As Integer, hostchoice As Integer)
Dim iCount As Integer
Dim temp As Integer
For iCount = 1 To 3
If userChoice1 <> iCount And hostchoice <> iCount Then temp = iCount
Next iCount
changeUserChoice = temp
End Function
Progress 4GL
editDEF TEMP-TABLE deur NO-UNDO
FIELD deurnr AS INT
FIELD prijsdeur AS LOG.
DEF VAR iprijsDeur AS INT NO-UNDO.
CREATE deur.
ASSIGN deur.deurnr = 1
deur.prijsdeur = FALSE.
CREATE deur.
ASSIGN deur.deurnr = 2
deur.prijsdeur = FALSE.
CREATE deur.
ASSIGN deur.deurnr = 3
deur.prijsdeur = FALSE.
iPrijsdeur = RANDOM(1,3).
FIND deur WHERE deurnr = iPrijsdeur.
ASSIGN prijsdeur = TRUE.
DEF VAR mijnkeuze AS INT NO-UNDO.
DEF VAR gamehostKeuze AS INT NO-UNDO.
DEF VAR mijnkeuze2 AS INT NO-UNDO.
DEF VAR i AS INT NO-UNDO.
DEF VAR g AS INT NO-UNDO.
DEF VAR v AS INT NO-UNDO.
DO i = 1 TO 100:
mijnkeuze = RANDOM(1,3).
gamehostkeuze = DYNAMIC-FUNCTION("openDeurZonderPrijs").
mijnkeuze2 = DYNAMIC-FUNCTION("wisselDeur").
/*mijnkeuze2 = mijnkeuze.*/
IF mijnkeuze2 = iPrijsdeur
THEN g = g + 1.
ELSE v = v + 1.
END.
MESSAGE "van" i "ronden won je er" g "en verloor je" v "keer".
FUNCTION openDeurZonderPrijs RETURNS INT:
FIND FIRST deur WHERE NOT deurnr EQ iPrijsdeur AND
NOT deurnr EQ mijnkeuze.
RETURN deur.deurnr.
END FUNCTION.
FUNCTION WisselDeur RETURN INT:
FIND deur WHERE NOT deurnr EQ mijnkeuze AND
NOT deurnr EQ gamehostkeuze.
RETURN deur.deurnr.
END FUNCTION.