/**
* Assignment 2. Monty Hall Problem
*
* Simulate the Monty Hall probability problem.
* Are you better off making a second door choice or
* staying with your first door choice to win the car?
* See https://en.wikipedia.org/wiki/Monty_Hall_problem
*
* Author: Ron Mak
* Department of Computer Science
* San Jose State University
*/
#include
#include
#include
#include
//#define NDEBUG
#include
using namespace std;
typedef int Door;
const int SIMULATION_COUNT = 100;
/**
* Run a simulation.
* @param sequence the sequence number.
* @param win1 number of first choice wins.
* @param win2 number of second choice wins.
*/
void simulate(int sequence, int& win1, int& win2);
/**
* Hide the car behind a door.
* @return the door that the car is hidden behind.
*/
Door hide_car();
/**
* @return the player's first door choice, which is either 1, 2, or 3.
*/
Door make_first_choice();
/**
* Open a door that is not:
* @param first_choice_door the player's first door choice.
* @param car_behind_door the door that the car is hidden behind.
* @return the door to open.
*/
Door open_door(Door first_choice_door, Door car_behind_door);
/**
* Return the player's second door choice, which cannot be:
* @param first_door the player's first choice door.
* @param opened_door the opened door.
* @return the second door choice.
*/
Door make_second_choice(Door first_door, Door opened_door);
/**
* @return a random door 1, 2, or 3.
*/
Door random_door();
/**
* Return a random door 1, 2, or 3 that is not:
* @param a_door a door.
* @param another_door another door, which can be equal to a_door.
* @return the random door.
*/
Door random_door_not(Door a_door, Door another_door);
/**
* Choose door 1, 2, or 3 that is not:
* @param first_door the player's first door choice.
* @param opened_door the opened door.
* @return the remaining door.
*/
Door choose_remaining_door(Door first_door, Door opened_door);
/**
* Main
*/
int main()
{
int win1 = 0, win2 = 0;
cout << " # Car First Opened Second Win Win" << endl;
cout << " here choice door choice first second" << endl;
cout << endl;
srand(time(NULL)); // seed the random number generator
// Run the simulations.
for (int i = 1; i <= SIMULATION_COUNT; i++) simulate(i, win1, win2);
cout << endl;
cout << setw(4) << win1 << " wins if stay with the first choice" << endl;
cout << setw(4) << win2 << " wins if switch to the second choice" << endl;
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(1);
cout << endl;
cout << "Win ratio of switch over stay: ";
cout << static_cast(win2)/win1 << endl;
}
void simulate(int sequence, int& win1, int& win2)
{
// Perform a simulation.
Door car_behind_door = hide_car();
Door first_choice_door = make_first_choice();
Door opened_door = open_door(first_choice_door,
car_behind_door);
Door second_choice_door = make_second_choice(first_choice_door,
opened_door);
// Print the results.
cout << setw(4) << sequence << setw(8) << car_behind_door;
cout << setw(8) << first_choice_door << setw(8) << opened_door;
cout << setw(8) << second_choice_door;
if (first_choice_door == car_behind_door)
{
cout << " yes"; // the car was behind the first door choice
win1++;
}
else
{
cout << " yes"; // it was behind the second door choice
win2++;
}
cout << endl;
}
Door hide_car()
{
// The simulation randomly chooses the door to hide the car.
return random_door();
}
Door make_first_choice()
{
// The simulation randomly makes the player's first door choice.
return random_door();
}
Door open_door(Door first_choice_door, Door car_behind_door)
{
// Monty Hall knows which door the car is behind
// and so he opens a door that has a goat behind it.
Door opened_door = random_door_not(first_choice_door, car_behind_door);
assert( (opened_door != first_choice_door)
&& (opened_door != car_behind_door));
return opened_door;
}
Door make_second_choice(Door first_door, Door opened_door)
{
// The player's second door choice can't be
// the first door choice or the opened door.
Door second_choice = choose_remaining_door(first_door, opened_door);
assert( (second_choice != first_door)
&& (second_choice != opened_door));
return second_choice;
}
Door random_door()
{
return rand()%3 + 1;
}
Door random_door_not(Door a_door, Door another_door)
{
Door door;
// If doors a_door and another_door are the same, then randomly
// choose between the other two doors to return.
// Otherwise, return the third door.
do {
door = random_door();
} while ((door == a_door) || (door == another_door));
return door;
}
Door choose_remaining_door(Door first_door, Door opened_door)
{
// Check door 1 and door 2.
for (Door door = 1; door <= 2; door++)
{
if ((door != first_door) && (door != opened_door)) return door;
}
return 3; // if not door 1 or door 2
}