Home |  Contact 
{developer} / {analyst}
  
  
  
  
  
  
  
  
  
  
  

The Monty Hall Gameshow Problem

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));

}