Algorithm Implementation/Simulation/Monty Hall problem
Haskell
import System.Random (newStdGen, randomRs) games = 10000 main = do cars <- pick 1 3 players <- pick 1 3 hosts <- pick 0 1 print . length . filter id . take games . zipWith3 monty cars players hosts where pick n m = randomRs (n, m :: Int) `fmap` newStdGen monty :: Int -> Int -> Int -> Bool monty car player host = head [door | door <- [1..3], door /= player, door /= hostChoice] == car where hostChoice = case [door | door <- [1..3], door /= player, door /= car] of [goat] -> goat goats -> goats !! host
Javascript
Array.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
import 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"); } }
C++
#include <iostream> #include <cstdlib> #include <ctime> #include <vector> #include <algorithm> using namespace std; int main() { srand(time(NULL)); unsigned long long stay = 0; unsigned long long change = 0; while(true) { vector<bool> boxes(3, false); boxes[0] = true; // Place a car random_shuffle(boxes.begin(), boxes.end()); 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; } }
Python
#!/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 xrange(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!"
R
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="")
[from http://sas-and-r.blogspot.com/search?q=7.23]
Ruby
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]) 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}%"
SAS
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;
[from http://sas-and-r.blogspot.com/search?q=7.23]
Visual Basic
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
DEF 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.