|
|
 | Monty Hall Simulation uses fast C code to perform simulation thousands of time |
|
This is a very famous problem that first appeared in an American journal section called 'Ask Marilyn'
in 1990. It has baffled even the best mathematicians as it is so counter intuitive.
Here's the situation. You are the contestant on a game show. You are asked to choose from three
closed doors. Behind one of the doors is a car, the others conceal goats. You make your choice and
the gameshow host then opens one of the two remaining doors to reveal a goat. He gives you the chance
to switch to the unchosen, unopen door. The question is, should you?
I read this puzzle in three different books and liked it so much that I decide to write a small C program
to run a simulation of the outcome of switching and sticking. This is called a Monte Carlo
simulation. I have included the code below.
It turns out that always switching will double your chances of winning to 2 out of 3. Can you work
out why?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define TOTAL_DOORS 3
#define ITERATIONS 10000
#define TRUE 1
#define FALSE 0
#define CAR 1
#define GOAT 0
typedef unsigned int BOOL;
int random(int min, int max)
{
return min + (rand() % (max - min));
}
void getunchosen(int doors[], int unchosen[], int chosen)
{
int i;
int j = 0;
for (i = 0; i < TOTAL_DOORS; i++)
{
if (i != chosen)
unchosen[j++] = i;
}
}
int openfalse(int doors[], int unchosen[])
{
/* the two remaining unchosen doors are
either both goats or a goat and a car
this method returns the index into doors
of the unselected, unopened door
permutations
door door action action
G G open return
G C open return
C G return open
*/
if (doors[unchosen[0]] == CAR)
/* it's a car return this and open other goat door */
return unchosen[0];
else // it's a goat, open this door and return the other one
return unchosen[1];
}
BOOL game(int change)
{
int choice; // stores the index of doors
// define doors
int doors[] = {GOAT, GOAT, GOAT};
// unchosen doors
int unchosen[TOTAL_DOORS - 1];
// randomly put a car "behind" one of them
doors[random(0, TOTAL_DOORS)] = CAR;
// randomly select a door
choice = doors[random(0, TOTAL_DOORS)];
// populate unchosen doors array
getunchosen(doors, unchosen, choice);
/* if switching, open a "false" door and
switch to the other one */
if (change)
choice = openfalse(doors, unchosen);
// did we win?
return doors[choice] == CAR;
}
int main(char** args)
{
int win = 0, lose = 0, i;
//seed the random function
srand( (unsigned)time( NULL ) );
// switching
for (i = 0; i < ITERATIONS; i++)
{
if (game(TRUE))
win++;
else
lose++;
}
printf("After %d iterations and SWITCHING:\n", ITERATIONS);
printf("wins = %d, losses = %d, win rate = %f\n",
win, lose, 100*(float)win/(win + lose));
// sticking
win = lose = 0;
for (i = 0; i < ITERATIONS; i++)
{
if (game(FALSE))
win++;
else
lose++;
}
printf("After %d iterations and STICKING:\n", ITERATIONS);
printf("wins = %d, losses = %d, win rate = %f\n",
win, lose, 100*(float)win/(win + lose));
}
|