Algorithm Implementation/Simulation/Monty Hall problem

From Wikibooks, open books for an open world
Jump to: navigation, search

PHP[edit]

class 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 getResultats()
        {       
                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)->getResultats();

Javascript[edit]

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[edit]

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++[edit]

#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[edit]

#!/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[edit]

 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[edit]

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[edit]

 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[edit]

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[edit]

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.


References[edit]