Monty Hall problem: Difference between revisions

→‎{{header|Julia}}: A new entry for Julia
m (→‎{{header|Sidef}}: minor edit)
(→‎{{header|Julia}}: A new entry for Julia)
Line 1,839:
Wins when switching door 6630
</lang>
 
=={{header|Julia}}==
To make things interesting, I decided to generalize the problem to <tt>ncur</tt> doors and <tt>ncar</tt> cars. To allow the MC to always show a goat behind a door after the contestant chooses, <math>ncur-ncar \ge 2</math>.
 
I was was of two minds on the type of simulation to provide, so I wrote two different simulators. The literal simulator mimics the mechanics of the game as literally as possible, shuffling the arrangement of cars behind doors and randomizes all choices. This avoids any feel of cheating but results in rather complex code. The clean simulator implements the game more elegantly but it might look like cheating.
 
'''The Literal Simulation Function'''
<lang Julia>
function play_mh_literal{T<:Integer}(ncur::T=3, ncar::T=1)
ncar < ncur || throw(DomainError())
curtains = shuffle(collect(1:ncur))
cars = curtains[1:ncar]
goats = curtains[(ncar+1):end]
pick = rand(1:ncur)
isstickwin = pick in cars
deleteat!(curtains, findin(curtains, pick))
if !isstickwin
deleteat!(goats, findin(goats, pick))
end
if length(goats) > 0 # reveal goat
deleteat!(curtains, findin(curtains, shuffle(goats)[1]))
else # no goats, so reveal car
deleteat!(curtains, rand(1:(ncur-1)))
end
pick = shuffle(curtains)[1]
isswitchwin = pick in cars
return (isstickwin, isswitchwin)
end
</lang>
 
'''The Clean Simulation Function'''
<lang Julia>
function play_mh_clean{T<:Integer}(ncur::T=3, ncar::T=1)
ncar < ncur || throw(DomainError())
pick = rand(1:ncur)
isstickwin = pick <= ncar
pick = rand(1:(ncur-2))
if isstickwin # remove initially picked car from consideration
pick += 1
end
isswitchwin = pick <= ncar
return (isstickwin, isswitchwin)
end
</lang>
 
'''Supporting Functions'''
<lang Julia>
function mh_results{T<:Integer}(ncur::T, ncar::T,
nruns::T, play_mh::Function)
stickwins = 0
switchwins = 0
for i in 1:nruns
(isstickwin, isswitchwin) = play_mh(ncur, ncar)
if isstickwin
stickwins += 1
end
if isswitchwin
switchwins += 1
end
end
return (stickwins/nruns, switchwins/nruns)
end
 
function mh_analytic{T<:Integer}(ncur::T, ncar::T)
stickodds = ncar/ncur
switchodds = (ncar - stickodds)/(ncur-2)
return (stickodds, switchodds)
end
 
function show_odds{T<:Real}(a::T, b::T)
@sprintf " %.1f %.1f %.2f" 100.0*a 100*b 1.0*b/a
end
 
function show_simulation{T<:Integer}(ncur::T, ncar::T, nruns::T)
println()
print("Simulating a ", ncur, " door, ", ncar, " car ")
println("Monty Hall problem with ", nruns, " runs.\n")
 
println(" Solution Stick Switch Improvement")
 
(a, b) = mh_results(ncur, ncar, nruns, play_mh_literal)
println(@sprintf("%10s: ", "Literal"), show_odds(a, b))
 
(a, b) = mh_results(ncur, ncar, nruns, play_mh_clean)
println(@sprintf("%10s: ", "Clean"), show_odds(a, b))
 
(a, b) = mh_analytic(ncur, ncar)
println(@sprintf("%10s: ", "Analytic"), show_odds(a, b))
println()
return nothing
end
</lang>
 
'''Main'''
<lang Julia>
for i in 3:5, j in 1:(i-2)
show_simulation(i, j, 10^5)
end
</lang>
 
This code shows, for a variety of configurations, the results for 3 solutions: literal simulation, clean simulation, analytic. Stick is the percentage of times that the player wins a car by sticking to an initial choice. Switch is the winning percentage the comes with switching one's selection following the goat reveal. Improvement is the ratio of switch to stick.
{{out}}
<pre>
Simulating a 3 door, 1 car Monty Hall problem with 100000 runs.
 
Solution Stick Switch Improvement
Literal: 33.2 66.8 2.02
Clean: 33.4 66.6 2.00
Analytic: 33.3 66.7 2.00
 
 
Simulating a 4 door, 1 car Monty Hall problem with 100000 runs.
 
Solution Stick Switch Improvement
Literal: 25.1 37.5 1.49
Clean: 24.7 37.6 1.52
Analytic: 25.0 37.5 1.50
 
 
Simulating a 4 door, 2 car Monty Hall problem with 100000 runs.
 
Solution Stick Switch Improvement
Literal: 49.7 75.3 1.51
Clean: 49.9 74.9 1.50
Analytic: 50.0 75.0 1.50
 
 
Simulating a 5 door, 1 car Monty Hall problem with 100000 runs.
 
Solution Stick Switch Improvement
Literal: 20.2 26.5 1.31
Clean: 20.0 26.8 1.34
Analytic: 20.0 26.7 1.33
 
 
Simulating a 5 door, 2 car Monty Hall problem with 100000 runs.
 
Solution Stick Switch Improvement
Literal: 40.0 53.5 1.34
Clean: 40.4 53.4 1.32
Analytic: 40.0 53.3 1.33
 
 
Simulating a 5 door, 3 car Monty Hall problem with 100000 runs.
 
Solution Stick Switch Improvement
Literal: 60.3 79.9 1.33
Clean: 59.9 80.1 1.34
Analytic: 60.0 80.0 1.33
</pre>
 
'''Literal versus Clean'''
 
The clean simulation runs significantly faster and uses less memory.
<pre>
julia> @time mh_results(3, 1, 10^5, play_mh_literal)
elapsed time: 0.346965522 seconds (183790752 bytes allocated, 27.56% gc time)
(0.33216,0.66784)
 
julia> @time mh_results(3, 1, 10^5, play_mh_clean)
elapsed time: 0.046481738 seconds (9600160 bytes allocated)
(0.33241,0.66759)
</pre>
 
=={{Header|Liberty BASIC}}==