Monty Hall problem: Difference between revisions

m
Fixed lang tags.
(→‎{{header|Perl 6}}: Changed to call &pick less often.)
m (Fixed lang tags.)
Line 132:
{{works with|ALGOL 68G|Any - tested with release mk15-0.8b.fc9.i386}}
{{works with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release 1.8.8d.fc9.i386}}
<lang algolalgol68>INT trials=100 000;
 
PROC brand = (INT n)INT: 1 + ENTIER (n * random);
Line 194:
 
=={{header|AWK}}==
<lang awk>#!/bin/gawk -f
<pre>
#!/bin/gawk -f
 
# Monty Hall problem
Line 251 ⟶ 250:
simulate(RAND)
}</lang>
}
</pre>
Sample output:
<lang awk>bash$ ./monty_hall.awk
<pre>
bash$ ./monty_hall.awk
 
Monty Hall problem simulation:
Line 263 ⟶ 260:
Algorithm switch: prize count = 6655, = 66.55%
Algorithm random: prize count = 4991, = 49.91%
bash$</prelang>
 
=={{header|BASIC}}==
Line 500 ⟶ 497:
 
=={{header|Forth}}==
<lang forth> 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</lang>
 
or in iForth:
 
<lang forth> 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." ;</lang>
 
With output:
Line 543 ⟶ 540:
=={{header|Fortran}}==
{{works with|Fortran|90 and later}}
<lang fortran> 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</lang>
Sample Output
Chance of winning by not switching is 32.82%
Line 594 ⟶ 591:
 
=={{header|Haskell}}==
<prelang haskell>import System.Random (StdGen, getStdGen, randomR)
 
trials :: Int
Line 627 ⟶ 624:
percent n ++ "% of the time."
percent n = show $ round $
100 * (fromIntegral n) / (fromIntegral trials)</prelang>
 
{{libheader|mtl}}
With a <tt>State</tt> monad, we can avoid having to explicitly pass around the <tt>StdGen</tt> so often. <tt>play</tt> and <tt>cars</tt> can be rewritten as follows:
 
<prelang haskell>import Control.Monad.State
 
play :: Bool -> State StdGen Door
Line 652 ⟶ 649:
cars n switch g = (numcars, new_g)
where numcars = length $ filter (== Car) prize_list
(prize_list, new_g) = runState (replicateM n (play switch)) g</prelang>
 
Sample output (for either implementation):
<lang haskell>The switch strategy succeeds 67% of the time.
<pre>
The switchstay strategy succeeds 6734% of the time.</lang>
The stay strategy succeeds 34% of the time.
</pre>
 
=={{header|J}}==
 
<lang j>NB. Monty Hall Simulation (a tacit version)
<lang j>
NB. Monty Hall Simulation (a tacit version)
'SIZE CAR STAY MONTY SWITCH DOORS ALL'=. i.7 NB. Setting mnemonics for boxes
f=. &({::) NB. Fetching the contents of a box
o=. @: NB. Composing verbs (functions)
pick=. (? @ #) { ] NB. Picking randomly an element from a vector
freq=. +/ % #
PickDoors=. (SIZE f ?@$ DOORS f) NB. Picking doors randomly
boxes=. < , a: $~ 6: NB. Appending 6 (empty) boxes to the input
 
'SIZE CAR STAY MONTY SWITCH DOORS ALL'=. i.7 NB. Setting mnemonics for boxes
doors=. < o 3: DOORS} ] NB. 3 doors
f=. &({::) car=. < o PickDoors CAR} ] NB. RandomizingFetching the carcontents of doora positionsbox
o=. @: stay=. < o PickDoors STAY} ] NB. Randomizing stayComposing doorverbs selections(functions)
 
all=. < o (i. o (DOORS f)) ALL} ] NB. All doors set
pick=. (? @ #) { ] NB. Picking randomly an element from a vector
Monty=. < o ((pick&>) o (ALL f (< @ -.)"1 (CAR f ,"0 STAY f))) MONTY } ]
freq=. +/ % #
NB. Calculating Monty's selections
PickDoors=. (SIZE f ?@$ DOORS f) NB. Picking doors randomly
switch=. < o (, o ((ALL f) -."1 (MONTY f) ,"0 (STAY f))) SWITCH } ]
 
NB. Calculating switching selections
boxes=. < , a: $~ 6: NB. Appending 6 (empty) boxes to the input
StayDisplay=. 'Stay: ' , ": o (CAR f freq o = STAY f)
 
SwitchDisplay=. 'Switch: ' , ": o (CAR f freq o = SWITCH f)
doors=. < o 3: DOORS} ] NB. 3 doors
car=. < o PickDoors CAR} ] NB. Randomizing car door positions
sim=. (StayDisplay ; SwitchDisplay) o switch o Monty o all o stay o car o doors o boxes f.
stay=. < o PickDoors STAY} ] NB. Randomizing stay door selections
</lang>
all=. < o (i. o (DOORS f)) ALL} ] NB. All doors set
Monty=. < o ((pick&>) o (ALL f (< @ -.)"1 (CAR f ,"0 STAY f))) MONTY } ]
NB. Calculating Monty's selections
switch=. < o (, o ((ALL f) -."1 (MONTY f) ,"0 (STAY f))) SWITCH } ]
NB. Calculating switching selections
StayDisplay=. 'Stay: ' , ": o (CAR f freq o = STAY f)
SwitchDisplay=. 'Switch: ' , ": o (CAR f freq o = SWITCH f)
 
sim=. (StayDisplay ; SwitchDisplay) o switch o Monty o all o stay o car o doors o boxes f.</lang>
Example:
<lang j> sim 1000000
sim 1000000
+--------------+----------------+
|Stay: 0.333143|Switch: 0.666857|
+--------------+----------------+</lang>
</lang>
 
=={{header|Java}}==
Line 727 ⟶ 718:
 
=={{header|MAXScript}}==
<lang maxscript>fn montyHall choice switch =
<pre>
fn montyHall choice switch =
(
doors = #(false, false, false)
Line 752 ⟶ 742:
iterations = 10000
format ("Stay strategy:%\%\n") (iterate iterations false)
format ("Switch strategy:%\%\n") (iterate iterations true)</lang>
</pre>
Output:
<prelang maxscript>Stay strategy:33.77%
Switch strategy:66.84%</prelang>
 
=={{header|OCaml}}==
Line 959 ⟶ 948:
=={{header|R}}==
 
<lang r> # 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)
 
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)
## To go with the exact parameters of the Rosetta challenge, complicating matters....
other_door <- 2 + (true_answers != 2)
## 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
## if always switch
## that he gives the player a second choice between the two remaining unopened doors.
summary( other_door == true_answers )
## if we never switch
N <- 10000 #trials
summary( true_answers <-== sample(1:3, N, replace=TRUE)
## if we randomly switch
user_choice <- sample(1:3, N, replace=TRUE)
random_switch <- other_door
## the host_choice is more complicated
random_switch[runif(N) >= .5] <- 1
host_chooser <- function(user_prize) {
summary(random_switch == true_answers)
# 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]
## To go with the exact parameters of the Rosetta challenge, complicating matters....
# if the first arg to sample is an int, it treats it as the number of choices
## Note that the player may initially choose any of the three doors (not just Door 1),
if (length(choices) == 1) { return(choices)}
## that the host opens a different door revealing a goat (not necessarily Door 3), and
else { return(sample(choices,1))}
## that he gives the player a second choice between the two remaining unopened doors.
}
 
N <- 10000 #trials
host_choice <- apply( X=cbind(true_answers,user_choice), FUN=host_chooser,MARGIN=1)
true_answers <- sample(1:3, N, replace=TRUE)
not_door <- function(x){ return( (1:3)[-x]) } # we could also define this
user_choice <- sample(1:3, N, replace=TRUE)
# directly at the FUN argument following
## the host_choice is more complicated
other_door <- apply( X = cbind(user_choice,host_choice), FUN=not_door, MARGIN=1)
host_chooser <- function(user_prize) {
# this could be cleaner
bad_choices <- unique(user_prize)
## if always switch
# in R, the x[-vector] form implies, choose the indices in x not in vector
summary( other_door == true_answers )
choices <- c(1:3)[-bad_choices]
## if we never switch
# if the first arg to sample is an int, it treats it as the number of choices
summary( true_answers == user_choice)
if (length(choices) == 1) { return(choices)}
## if we randomly switch
else { return(sample(choices,1))}
random_switch <- user_choice
}
change <- runif(N) >= .5
 
random_switch[change] <- other_door[change]
host_choice <- apply( X=cbind(true_answers,user_choice), FUN=host_chooser,MARGIN=1)
summary(random_switch == true_answers)</lang>
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)</lang>
 
 
Line 1,250 ⟶ 1,239:
for the switching strategy.
 
<lang Ursala>#import std
#import std
#import nat
#import flo
Line 1,267 ⟶ 1,255:
#show+
 
main = ~&plrTS/<'stay: ','switch: '> format* <staying_wins,switching_wins></lang>
</lang>
Output will vary slightly for each run due to randomness.
<pre>
Line 1,279 ⟶ 1,266:
 
Vedit macro language does not have random number generator, so one is implemented in subroutine RANDOM (the algorithm was taken from ANSI C library).
<lang vedit>#90 = Time_Tick // seed for random number generator
<lang vedit>
#90 = Time_Tick // seed for random number generator
#91 = 3 // random numbers in range 0 to 2
#1 = 0 // wins for "always stay" strategy
Line 1,313 ⟶ 1,299:
#93 = 0x7fffffff % 48271
#90 = (48271 * (#90 % #92) - #93 * (#90 / #92)) & 0x7fffffff
return ((#90 & 0xffff) * #91 / 0x10000)</lang>
</lang>
 
Sample output:
Anonymous user