/**
 * Monty Hall's game simulator... 
 * 
 * Calculates win percentages when you keep your original door or change your mind
 * in a monty hall problem - http://en.wikipedia.org/wiki/Monty_Hall_problem
 *
 * Author: Timothy C. Fanelli
 * Date: April 10, 2008
 **/

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cassert>
using namespace std;

int main() {
  int iterations;
  bool contents[] = { false, false, false };

  cout << "How many iterations: ";
  cin >> iterations;

  int changedDoorCount = 0;
  int correct[] = {0, 0};

  srand( time( 0 ) );

  for ( int i = 0; i < iterations; ++i ) {
    int goatOne, goatTwo;
    int carIdx = rand() % 3;

    // Setup the monty hall's doors:
    contents[0] = false;
    contents[1] = false;
    contents[2] = false;
    contents[carIdx] = true;

    if ( carIdx == 0 ) {
      goatOne = 1;
      goatTwo = 2;
    } 
    else if ( carIdx == 1 ) {
      goatOne = 0;
      goatTwo = 2;
    } 
    else {
      goatOne = 0;
      goatTwo = 1;
    }

    // So:
    //   contents[carIdx]  == true
    //   contents[goatOne] == false
    //   contents[goatTwo] == false

    assert( contents[carIdx] );
    assert( ! contents[goatOne] );
    assert( ! contents[goatTwo] );

    // Simulate an initial choice, then expose a goat:
    int userChoice = rand() % 3;
    int doorExposed = (goatOne==userChoice)?goatTwo:goatOne;

    // Do we change doors?
    bool changedDoors = rand() % 2;

    if ( changedDoors ) {
      changedDoorCount++;

      // Pick the door that isn't the user's choice 
      // and isn't the exposedDoor... note: 
      //
      // userChoice != doorExposed by design.

      if ( userChoice == 0 ) 
      {
	if ( doorExposed == 1 ) 
	  userChoice = 2;
	else 
	  userChoice == 1;
      }
      else if ( userChoice == 1 ) 
      {
	if ( doorExposed == 0 ) 
	  userChoice = 2;
	else 
	  userChoice = 0;
      }
      else
      {
	if ( doorExposed == 0 ) 
	  userChoice = 1;
	else 
	  userChoice = 0;
      }

      assert( userChoice != doorExposed );
    }

    // Track how many times we chose correctly -
    //   Increment correct[0] if we kept our original choice
    //   Increment correct[1] if we chose the other door.

    if ( contents[userChoice] ) {
      correct[ changedDoors ]++;
    }
  }

  double changedWinPercent = 100*(correct[1]/static_cast<double>(changedDoorCount));
  double originalWinPercent = 100*(correct[0]/static_cast<double>(iterations-changedDoorCount));
  double totalWinPercent = (correct[0]+correct[1]) / static_cast<double>( iterations ) * 100;

  cout << "In " << iterations << " runs, we won a car " << totalWinPercent << "% of the time." << endl;

  cout << "\tUsed original choice and won a car " << correct[0] 
       << " out of " << iterations - changedDoorCount << " times... " 
       << originalWinPercent << "%" << endl;

  cout << "\tChose the other door and won a car " << correct[1] 
       << " out of " << changedDoorCount << " times... " 
       << changedWinPercent << "%" << endl;
}
