Monty Hall problem: Difference between revisions

m
Semi-automated edit: Bash -> UNIX Shell
m (Semi-automated edit: Bash -> UNIX Shell)
Line 316:
Algorithm random: prize count = 4991, = 49.91%
bash$</lang>
 
=={{header|bash}}==
{{works with|bash|2.x| and most bash-compatible unix shells}}
<lang bash>
#!/bin/bash
# Simulates the "monty hall" probability paradox and shows results.
# http://en.wikipedia.org/wiki/Monty_Hall_problem
# (should rewrite this in C for faster calculating of huge number of rounds)
# (Hacked up by Éric Tremblay, 07.dec.2010)
 
num_rounds=10 #default number of rounds
num_doors=3 # default number of doors
[ "$1" = "" ] || num_rounds=$[$1+0]
[ "$2" = "" ] || num_doors=$[$2+0]
 
nbase=1 # or 0 if we want to see door numbers zero-based
num_win=0; num_lose=0
 
echo "Playing $num_rounds times, with $num_doors doors."
[ "$num_doors" -lt 3 ] && {
echo "Hey, there has to be at least 3 doors!!"
exit 1
}
echo
 
function one_round() {
winning_door=$[$RANDOM % $num_doors ]
player_picks_door=$[$RANDOM % $num_doors ]
 
# Host leaves this door AND the player's first choice closed, opens all others
# (this WILL loop forever if there is only 1 door)
host_skips_door=$winning_door
while [ "$host_skips_door" = "$player_picks_door" ]; do
#echo -n "(Host looks at door $host_skips_door...) "
host_skips_door=$[$RANDOM % $num_doors]
done
# Output the result of this round
#echo "Round $[$nbase+current_round]: "
echo -n "Player chooses #$[$nbase+$player_picks_door]. "
[ "$num_doors" -ge 10 ] &&
# listing too many door numbers (10 or more) will just clutter the output
echo -n "Host opens all except #$[$nbase+$host_skips_door] and #$[$nbase+$player_picks_door]. " \
|| {
# less than 10 doors, we list them one by one instead of "all except ?? and ??"
echo -n "Host opens"
host_opens=0
while [ "$host_opens" -lt "$num_doors" ]; do
[ "$host_opens" != "$host_skips_door" ] && [ "$host_opens" != "$player_picks_door" ] && \
echo -n " #$[$nbase+$host_opens]"
host_opens=$[$host_opens+1]
done
echo -n " "
}
echo -n "(prize is behind #$[$nbase+$winning_door]) "
echo -n "Switch from $[$nbase+$player_picks_door] to $[$nbase+$host_skips_door]: "
[ "$winning_door" = "$host_skips_door" ] && {
echo "WIN."
num_win=$[num_win+1]
} || {
echo "LOSE."
num_lose=$[num_lose+1]
}
} # end of function one_round
 
# ok, let's go
current_round=0
while [ "$num_rounds" -gt "$current_round" ]; do
one_round
current_round=$[$current_round+1]
done
 
echo
echo "Wins (switch to remaining door): $num_win"
echo "Losses (first guess was correct): $num_lose"
exit 0
</lang>
Output of a few runs:
<pre>
$ ./monty_hall_problem.sh
Playing 10 times, with 3 doors.
 
Player chooses #2. Host opens #3 (prize is behind #1) Switch from 2 to 1: WIN.
Player chooses #1. Host opens #3 (prize is behind #2) Switch from 1 to 2: WIN.
Player chooses #2. Host opens #3 (prize is behind #2) Switch from 2 to 1: LOSE.
Player chooses #1. Host opens #2 (prize is behind #1) Switch from 1 to 3: LOSE.
Player chooses #2. Host opens #3 (prize is behind #1) Switch from 2 to 1: WIN.
Player chooses #2. Host opens #1 (prize is behind #2) Switch from 2 to 3: LOSE.
Player chooses #3. Host opens #1 (prize is behind #2) Switch from 3 to 2: WIN.
Player chooses #2. Host opens #1 (prize is behind #3) Switch from 2 to 3: WIN.
Player chooses #1. Host opens #3 (prize is behind #1) Switch from 1 to 2: LOSE.
Player chooses #1. Host opens #2 (prize is behind #3) Switch from 1 to 3: WIN.
 
Wins (switch to remaining door): 6
Losses (first guess was correct): 4
 
 
$ ./monty_hall_problem.sh 5 10
Playing 5 times, with 10 doors.
 
Player chooses #1. Host opens all except #10 and #1. (prize is behind #10) Switch from 1 to 10: WIN.
Player chooses #7. Host opens all except #8 and #7. (prize is behind #8) Switch from 7 to 8: WIN.
Player chooses #6. Host opens all except #1 and #6. (prize is behind #1) Switch from 6 to 1: WIN.
Player chooses #8. Host opens all except #3 and #8. (prize is behind #8) Switch from 8 to 3: LOSE.
Player chooses #6. Host opens all except #5 and #6. (prize is behind #5) Switch from 6 to 5: WIN.
 
Wins (switch to remaining door): 4
Losses (first guess was correct): 1
 
 
$ ./monty_hall_problem.sh 1000
Playing 1000 times, with 3 doors.
 
Player chooses #2. Host opens #1 (prize is behind #2) Switch from 2 to 3: LOSE.
Player chooses #3. Host opens #1 (prize is behind #2) Switch from 3 to 2: WIN.
[ ... ]
Player chooses #1. Host opens #3 (prize is behind #2) Switch from 1 to 2: WIN.
Player chooses #3. Host opens #2 (prize is behind #1) Switch from 3 to 1: WIN.
 
Wins (switch to remaining door): 655
Losses (first guess was correct): 345
</pre>
 
=={{header|BASIC}}==
Line 536 ⟶ 414:
Changing: 66.59
New random choice: 49.67</pre>
 
=={{header|C sharp|C#}}==
{{trans|Java}}
 
<lang C sharp>
using System;
 
namespace MontyHallProblem
{
class Program
{
static void Main(string[] args)
{
int switchWins = 0;
int stayWins = 0;
 
Random gen = new Random();
for(int plays = 0; plays < 1000000; plays++ )
{
int[] doors = {0,0,0};//0 is a goat, 1 is a car
 
var winner = gen.Next(3);
doors[winner] = 1; //put a winner in a random door
int choice = gen.Next(3); //pick a door, any door
int shown; //the shown door
do
{
shown = gen.Next(3);
}
while(doors[shown] == 1 || shown == choice); //don't show the winner or the choice
stayWins += doors[choice];//if you won by staying, count it
//the switched (last remaining) door is (3 - choice - shown), because 0+1+2=3
switchWins += doors[3 - choice - shown];
}
 
System.Console.Out.Write("Switching wins " + switchWins + " times.");
System.Console.Out.Write("Staying wins " + stayWins + " times.");
}
}
}
</lang>
 
Sample output:
<pre>
Staying winns: 333830
Switching winns: 666170
</pre>
 
=={{header|C++}}==
<lang cpp>#include <iostream>
#include <cstdlib>
#include <ctime>
int randint(int n)
{
return (1.0*n*std::rand())/(1.0+RAND_MAX);
}
 
int other(int doorA, int doorB)
{
int doorC;
if (doorA == doorB)
{
doorC = randint(2);
if (doorC >= doorA)
++doorC;
}
else
{
for (doorC = 0; doorC == doorA || doorC == doorB; ++doorC)
{
// empty
}
}
return doorC;
}
 
int check(int games, bool change)
{
int win_count = 0;
for (int game = 0; game < games; ++game)
{
int const winning_door = randint(3);
int const original_choice = randint(3);
int open_door = other(original_choice, winning_door);
 
int const selected_door = change?
other(open_door, original_choice)
: original_choice;
 
if (selected_door == winning_door)
++win_count;
}
return win_count;
}
int main()
{
std::srand(std::time(0));
 
int games = 10000;
int wins_stay = check(games, false);
int wins_change = check(games, true);
std::cout << "staying: " << 100.0*wins_stay/games << "%, changing: " << 100.0*wins_change/games << "%\n";
}</lang>
Sample output:
staying: 33.73%, changing: 66.9%
 
=={{header|Clojure}}==
Line 644 ⟶ 634:
Stay: 33.2716%
Switch: 66.6593%</lang>
 
=={{header|C++}}==
<lang cpp>#include <iostream>
#include <cstdlib>
#include <ctime>
int randint(int n)
{
return (1.0*n*std::rand())/(1.0+RAND_MAX);
}
 
int other(int doorA, int doorB)
{
int doorC;
if (doorA == doorB)
{
doorC = randint(2);
if (doorC >= doorA)
++doorC;
}
else
{
for (doorC = 0; doorC == doorA || doorC == doorB; ++doorC)
{
// empty
}
}
return doorC;
}
 
int check(int games, bool change)
{
int win_count = 0;
for (int game = 0; game < games; ++game)
{
int const winning_door = randint(3);
int const original_choice = randint(3);
int open_door = other(original_choice, winning_door);
 
int const selected_door = change?
other(open_door, original_choice)
: original_choice;
 
if (selected_door == winning_door)
++win_count;
}
return win_count;
}
int main()
{
std::srand(std::time(0));
 
int games = 10000;
int wins_stay = check(games, false);
int wins_change = check(games, true);
std::cout << "staying: " << 100.0*wins_stay/games << "%, changing: " << 100.0*wins_change/games << "%\n";
}</lang>
Sample output:
staying: 33.73%, changing: 66.9%
 
=={{header|C sharp|C#}}==
{{trans|Java}}
 
<lang C sharp>
using System;
 
namespace MontyHallProblem
{
class Program
{
static void Main(string[] args)
{
int switchWins = 0;
int stayWins = 0;
 
Random gen = new Random();
for(int plays = 0; plays < 1000000; plays++ )
{
int[] doors = {0,0,0};//0 is a goat, 1 is a car
 
var winner = gen.Next(3);
doors[winner] = 1; //put a winner in a random door
int choice = gen.Next(3); //pick a door, any door
int shown; //the shown door
do
{
shown = gen.Next(3);
}
while(doors[shown] == 1 || shown == choice); //don't show the winner or the choice
stayWins += doors[choice];//if you won by staying, count it
//the switched (last remaining) door is (3 - choice - shown), because 0+1+2=3
switchWins += doors[3 - choice - shown];
}
 
System.Console.Out.Write("Switching wins " + switchWins + " times.");
System.Console.Out.Write("Staying wins " + stayWins + " times.");
}
}
}
</lang>
 
Sample output:
<pre>
Staying winns: 333830
Switching winns: 666170
</pre>
 
=={{header|D}}==
Line 796 ⟶ 674:
Switching wins: 66673 Staying wins: 33327
</pre>
 
=={{header|F_Sharp|F#}}==
I don't bother with having Monty "pick" a door, since you only win if you initially pick a loser in the switch strategy and you only win if you initially pick a winner in the stay strategy so there doesn't seem to be much sense in playing around the background having Monty "pick" doors. Makes it pretty simple to see why it's always good to switch.
<lang fsharp>open System
let monty nSims =
let rnd = new Random()
let SwitchGame() =
let winner, pick = rnd.Next(0,3), rnd.Next(0,3)
if winner <> pick then 1 else 0
 
let StayGame() =
let winner, pick = rnd.Next(0,3), rnd.Next(0,3)
if winner = pick then 1 else 0
 
let Wins (f:unit -> int) = seq {for i in [1..nSims] -> f()} |> Seq.sum
printfn "Stay: %d wins out of %d - Switch: %d wins out of %d" (Wins StayGame) nSims (Wins SwitchGame) nSims</lang>
I had a very polite suggestion that I simulate Monty's "pick" so I'm putting in a version that does that. I compare the outcome with my original outcome and, unsurprisingly, show that this is essentially a noop that has no bearing on the output, but I (kind of) get where the request is coming from so here's that version...
<lang fsharp>let montySlower nSims =
let rnd = new Random()
let MontyPick winner pick =
if pick = winner then
[0..2] |> Seq.filter (fun i -> i <> pick) |> Seq.nth (rnd.Next(0,2))
else
3 - pick - winner
let SwitchGame() =
let winner, pick = rnd.Next(0,3), rnd.Next(0,3)
let monty = MontyPick winner pick
let pickFinal = 3 - monty - pick
 
// Show that Monty's pick has no effect...
 
if (winner <> pick) <> (pickFinal = winner) then
printfn "Monty's selection actually had an effect!"
if pickFinal = winner then 1 else 0
 
let StayGame() =
let winner, pick = rnd.Next(0,3), rnd.Next(0,3)
let monty = MontyPick winner pick
 
// This one's even more obvious than the above since pickFinal
// is precisely the same as pick
 
let pickFinal = pick
if (winner = pick) <> (winner = pickFinal) then
printfn "Monty's selection actually had an effect!"
if winner = pickFinal then 1 else 0
 
let Wins (f:unit -> int) = seq {for i in [1..nSims] -> f()} |> Seq.sum
printfn "Stay: %d wins out of %d - Switch: %d wins out of %d" (Wins StayGame) nSims (Wins SwitchGame) nSims</lang>
 
=={{header|Forth}}==
Line 890 ⟶ 817:
Chance of winning by not switching is 32.82%
Chance of winning by switching is 67.18%
 
=={{header|F_Sharp|F#}}==
I don't bother with having Monty "pick" a door, since you only win if you initially pick a loser in the switch strategy and you only win if you initially pick a winner in the stay strategy so there doesn't seem to be much sense in playing around the background having Monty "pick" doors. Makes it pretty simple to see why it's always good to switch.
<lang fsharp>open System
let monty nSims =
let rnd = new Random()
let SwitchGame() =
let winner, pick = rnd.Next(0,3), rnd.Next(0,3)
if winner <> pick then 1 else 0
 
let StayGame() =
let winner, pick = rnd.Next(0,3), rnd.Next(0,3)
if winner = pick then 1 else 0
 
let Wins (f:unit -> int) = seq {for i in [1..nSims] -> f()} |> Seq.sum
printfn "Stay: %d wins out of %d - Switch: %d wins out of %d" (Wins StayGame) nSims (Wins SwitchGame) nSims</lang>
I had a very polite suggestion that I simulate Monty's "pick" so I'm putting in a version that does that. I compare the outcome with my original outcome and, unsurprisingly, show that this is essentially a noop that has no bearing on the output, but I (kind of) get where the request is coming from so here's that version...
<lang fsharp>let montySlower nSims =
let rnd = new Random()
let MontyPick winner pick =
if pick = winner then
[0..2] |> Seq.filter (fun i -> i <> pick) |> Seq.nth (rnd.Next(0,2))
else
3 - pick - winner
let SwitchGame() =
let winner, pick = rnd.Next(0,3), rnd.Next(0,3)
let monty = MontyPick winner pick
let pickFinal = 3 - monty - pick
 
// Show that Monty's pick has no effect...
 
if (winner <> pick) <> (pickFinal = winner) then
printfn "Monty's selection actually had an effect!"
if pickFinal = winner then 1 else 0
 
let StayGame() =
let winner, pick = rnd.Next(0,3), rnd.Next(0,3)
let monty = MontyPick winner pick
 
// This one's even more obvious than the above since pickFinal
// is precisely the same as pick
 
let pickFinal = pick
if (winner = pick) <> (winner = pickFinal) then
printfn "Monty's selection actually had an effect!"
if winner = pickFinal then 1 else 0
 
let Wins (f:unit -> int) = seq {for i in [1..nSims] -> f()} |> Seq.sum
printfn "Stay: %d wins out of %d - Switch: %d wins out of %d" (Wins StayGame) nSims (Wins SwitchGame) nSims</lang>
 
=={{header|Haskell}}==
Line 2,005 ⟶ 1,883:
Estimate: 4960/10000 wins for 'picking anew' strategy
Of course, this challenge could also be tackled by putting up a GUI and letting the user be the source of the randomness. But that's moving away from the letter of the challenge and takes a lot of effort anyway...
 
=={{header|UNIX Shell}}==
{{works with|bash|2.x| and most bash-compatible unix shells}}
<lang bash>
#!/bin/bash
# Simulates the "monty hall" probability paradox and shows results.
# http://en.wikipedia.org/wiki/Monty_Hall_problem
# (should rewrite this in C for faster calculating of huge number of rounds)
# (Hacked up by Éric Tremblay, 07.dec.2010)
 
num_rounds=10 #default number of rounds
num_doors=3 # default number of doors
[ "$1" = "" ] || num_rounds=$[$1+0]
[ "$2" = "" ] || num_doors=$[$2+0]
 
nbase=1 # or 0 if we want to see door numbers zero-based
num_win=0; num_lose=0
 
echo "Playing $num_rounds times, with $num_doors doors."
[ "$num_doors" -lt 3 ] && {
echo "Hey, there has to be at least 3 doors!!"
exit 1
}
echo
 
function one_round() {
winning_door=$[$RANDOM % $num_doors ]
player_picks_door=$[$RANDOM % $num_doors ]
 
# Host leaves this door AND the player's first choice closed, opens all others
# (this WILL loop forever if there is only 1 door)
host_skips_door=$winning_door
while [ "$host_skips_door" = "$player_picks_door" ]; do
#echo -n "(Host looks at door $host_skips_door...) "
host_skips_door=$[$RANDOM % $num_doors]
done
# Output the result of this round
#echo "Round $[$nbase+current_round]: "
echo -n "Player chooses #$[$nbase+$player_picks_door]. "
[ "$num_doors" -ge 10 ] &&
# listing too many door numbers (10 or more) will just clutter the output
echo -n "Host opens all except #$[$nbase+$host_skips_door] and #$[$nbase+$player_picks_door]. " \
|| {
# less than 10 doors, we list them one by one instead of "all except ?? and ??"
echo -n "Host opens"
host_opens=0
while [ "$host_opens" -lt "$num_doors" ]; do
[ "$host_opens" != "$host_skips_door" ] && [ "$host_opens" != "$player_picks_door" ] && \
echo -n " #$[$nbase+$host_opens]"
host_opens=$[$host_opens+1]
done
echo -n " "
}
echo -n "(prize is behind #$[$nbase+$winning_door]) "
echo -n "Switch from $[$nbase+$player_picks_door] to $[$nbase+$host_skips_door]: "
[ "$winning_door" = "$host_skips_door" ] && {
echo "WIN."
num_win=$[num_win+1]
} || {
echo "LOSE."
num_lose=$[num_lose+1]
}
} # end of function one_round
 
# ok, let's go
current_round=0
while [ "$num_rounds" -gt "$current_round" ]; do
one_round
current_round=$[$current_round+1]
done
 
echo
echo "Wins (switch to remaining door): $num_win"
echo "Losses (first guess was correct): $num_lose"
exit 0
</lang>
Output of a few runs:
<pre>
$ ./monty_hall_problem.sh
Playing 10 times, with 3 doors.
 
Player chooses #2. Host opens #3 (prize is behind #1) Switch from 2 to 1: WIN.
Player chooses #1. Host opens #3 (prize is behind #2) Switch from 1 to 2: WIN.
Player chooses #2. Host opens #3 (prize is behind #2) Switch from 2 to 1: LOSE.
Player chooses #1. Host opens #2 (prize is behind #1) Switch from 1 to 3: LOSE.
Player chooses #2. Host opens #3 (prize is behind #1) Switch from 2 to 1: WIN.
Player chooses #2. Host opens #1 (prize is behind #2) Switch from 2 to 3: LOSE.
Player chooses #3. Host opens #1 (prize is behind #2) Switch from 3 to 2: WIN.
Player chooses #2. Host opens #1 (prize is behind #3) Switch from 2 to 3: WIN.
Player chooses #1. Host opens #3 (prize is behind #1) Switch from 1 to 2: LOSE.
Player chooses #1. Host opens #2 (prize is behind #3) Switch from 1 to 3: WIN.
 
Wins (switch to remaining door): 6
Losses (first guess was correct): 4
 
 
$ ./monty_hall_problem.sh 5 10
Playing 5 times, with 10 doors.
 
Player chooses #1. Host opens all except #10 and #1. (prize is behind #10) Switch from 1 to 10: WIN.
Player chooses #7. Host opens all except #8 and #7. (prize is behind #8) Switch from 7 to 8: WIN.
Player chooses #6. Host opens all except #1 and #6. (prize is behind #1) Switch from 6 to 1: WIN.
Player chooses #8. Host opens all except #3 and #8. (prize is behind #8) Switch from 8 to 3: LOSE.
Player chooses #6. Host opens all except #5 and #6. (prize is behind #5) Switch from 6 to 5: WIN.
 
Wins (switch to remaining door): 4
Losses (first guess was correct): 1
 
 
$ ./monty_hall_problem.sh 1000
Playing 1000 times, with 3 doors.
 
Player chooses #2. Host opens #1 (prize is behind #2) Switch from 2 to 3: LOSE.
Player chooses #3. Host opens #1 (prize is behind #2) Switch from 3 to 2: WIN.
[ ... ]
Player chooses #1. Host opens #3 (prize is behind #2) Switch from 1 to 2: WIN.
Player chooses #3. Host opens #2 (prize is behind #1) Switch from 3 to 1: WIN.
 
Wins (switch to remaining door): 655
Losses (first guess was correct): 345
</pre>
 
=={{header|Ursala}}==
Anonymous user