|
The television game show Let's Make a Deal was hosted by Monty Hall. The premise of the show was to
give contestants the opportunity to make choices in order to win prizes. A typical opportunity would go
like this:
Suppose you are a contestant on a game show, and you are given the choice of three doors: behind one door is a car; behind the other two are goats. You select a door, say Number 1, and the host, who knows what is behind each of the doors, opens another door, say Number 3, which has a goat. He then says to you, "Would you like to stay with door Number 1 or change your selection and go with door Number 2?"
Here is a program in C to simulate this situation.
// MONTY.C // Simulate the Monty Hall problem // Last revised April 26, 2012 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #define FALSE 0 #define TRUE (!FALSE) #define DOOR_ONE 0 #define DOOR_TWO 1 #define DOOR_THREE 2 #define PRIZE_GOAT 0 #define PRIZE_CAR 1 int get_random_door( void ) { switch( random() % 3 ) { case 0: return( DOOR_ONE ); case 1: return( DOOR_TWO ); case 2: return( DOOR_THREE ); } printf( "Bugcheck.\n" ); exit( 0 ); } void do_random_seeding( void ) { time_t time_now; time( &time_now ); srandom((unsigned int) time_now ); } char *text_door( int door_value ) { switch( door_value ) { case DOOR_ONE: return( "One" ); case DOOR_TWO: return( "Two" ); case DOOR_THREE: return( "Three" ); } printf( "Bugcheck.\n" ); exit( 0 ); } char *text_prize( int prize_value ) { switch( prize_value ) { case PRIZE_GOAT: return( "Goat" ); case PRIZE_CAR: return( "Car" ); } printf( "Bugcheck.\n" ); exit( 0 ); } int main( int argc, char *argv[] ) { int round; int door[ 3 ]; int number_of_rounds; int door_with_car; int stand_firm_car, stand_firm_goat; int switch_door_car, switch_door_goat; int print_trace_flag; int first_choice_door, host_revealed_door, remaining_door; int car_behind_door_count[ 3 ]; int first_choice_count[ 3 ]; number_of_rounds = 1; if ( argc > 1 ) { number_of_rounds = atoi( argv[1] ); if ( number_of_rounds < 1 ) { printf( "Must perform at least one round.\n" ); exit( 0 ); } } // If performing fewer than 20 rounds, show a detailed trace for each one print_trace_flag = ( number_of_rounds < 20 ) ? TRUE : FALSE; do_random_seeding(); // Keep track of wins and losses for each choice stand_firm_car = 0; stand_firm_goat = 0; switch_door_car = 0; switch_door_goat = 0; // Keep track of random choices in case our random source is biased car_behind_door_count[ DOOR_ONE ] = 0; car_behind_door_count[ DOOR_TWO ] = 0; car_behind_door_count[ DOOR_THREE ] = 0; first_choice_count[ DOOR_ONE ] = 0; first_choice_count[ DOOR_TWO ] = 0; first_choice_count[ DOOR_THREE ] = 0; // Perform each event for ( round = 1; round <= number_of_rounds; round++ ) { // Prepare each door prior to the event door[ DOOR_ONE ] = PRIZE_GOAT; door[ DOOR_TWO ] = PRIZE_GOAT; door[ DOOR_THREE ] = PRIZE_GOAT; // Place the car behind a random door door_with_car = get_random_door(); door[ door_with_car ] = PRIZE_CAR; // Keep track of which door what chosen for statistical purposes car_behind_door_count[ door_with_car ]++; if ( TRUE == print_trace_flag ) { printf( "Round %d:\n", round ); printf( " [ %4s ] [ %4s ] [ %4s ]\n", text_prize( door[ DOOR_ONE ] ), text_prize( door[ DOOR_TWO ] ), text_prize( door[ DOOR_THREE ] ) ); } // Contestant selects a door first_choice_door = get_random_door(); // Keep track of which door a contestant chooses for statistical purposes first_choice_count[ first_choice_door ]++; if ( TRUE == print_trace_flag ) { printf( " Contestant chooses door %s.\n", text_door( first_choice_door )); } // Host reveals a goat that is behind a door the contestant did not pick while( 1 ) { host_revealed_door = get_random_door(); // The host cannot reveal the door that the contestant chose if ( host_revealed_door == first_choice_door ) continue; // The host must reveal a goat if ( PRIZE_GOAT != door[ host_revealed_door ] ) continue; break; } if ( TRUE == print_trace_flag ) { printf( " Host reveals door %s as a %s.\n", text_door( host_revealed_door ), text_prize( door[ host_revealed_door ] )); } // Contestant stands firm if ( TRUE == print_trace_flag ) { printf( " Contestant does not switch and wins a %s.\n", text_prize( door[ first_choice_door ] )); } if ( PRIZE_CAR == door[ first_choice_door ] ) { stand_firm_car++; } else { stand_firm_goat++; } // Determine the remaining door remaining_door = DOOR_ONE + DOOR_TWO + DOOR_THREE; remaining_door -= first_choice_door; remaining_door -= host_revealed_door; // Contestant switches to the other door if ( TRUE == print_trace_flag ) { printf( " Contestant switches and wins a %s.\n", text_prize( door[ remaining_door ] )); } if ( PRIZE_CAR == door[ remaining_door ] ) { switch_door_car++; } else { switch_door_goat++; } } // Print summary information printf( "After %d roun%s:\n", number_of_rounds, ( 1 == number_of_rounds ) ? "d" : "ds" ); printf( " Do not switch: Win %d, Lose %d, %f%%.\n", stand_firm_car, stand_firm_goat, 100.0 * (float) stand_firm_car / (float) number_of_rounds ); printf( " Switch: Win %d, Lose %d, %f%%.\n", switch_door_car, switch_door_goat, 100.0 * (float) switch_door_car / (float) number_of_rounds ); printf( " Door with Car: One: %d, Two: %d, Three: %d.\n", car_behind_door_count[ DOOR_ONE ], car_behind_door_count[ DOOR_TWO ], car_behind_door_count[ DOOR_THREE ] ); printf( " First Chosen Door: One: %d, Two: %d, Three: %d.\n", first_choice_count[ DOOR_ONE ], first_choice_count[ DOOR_TWO ], first_choice_count[ DOOR_THREE ] ); printf( "\n" ); exit( 0 ); }
$ ./monty Round 1: [ Car ] [ Goat ] [ Goat ] Contestant chooses door Two. Host reveals door Three as a Goat. Contestant does not switch and wins a Goat. Contestant switches and wins a Car. After 1 round: Do not switch: Win 0, Lose 1, 0.000000%. Switch: Win 1, Lose 0, 100.000000%. Door with Car: One: 1, Two: 0, Three: 0. First Chosen Door: One: 0, Two: 1, Three: 0.
$ ./monty 1000000 After 1000000 rounds: Do not switch: Win 332851, Lose 667149, 33.285100%. Switch: Win 667149, Lose 332851, 66.714900%. Door with Car: One: 333127, Two: 334321, Three: 332552. First Chosen Door: One: 333071, Two: 334247, Three: 332682. |