/* Author: Ram Samudrala (me@ram.org)
 *
 * January 1, 1996.
 *
 * The problem: Game with three doors; 2 contains goats behind them.
 * 1 contains a car.  The contestant picks a door.  The host (who
 * knows what's behind the doors) opens another door revealing a
 * goat.  The contestant is then given an option to re-choose between
 * the remaining two doors.  Should the contestant switch?
 *
 * The answer is yes, since the probability increases from 1/3 to
 * 2/3.  This simulates the above problem, and shows what happens if
 * the switching is done randomly.  The contestant is right 2/3 of the
 * times a switch is made.
 * 
 */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define MAX_TRIALS 1000000000

int get_random(int val1, int val2);
int choose_door_host_opens(int answer, int door_choice);
int get_door_choice(int current_choice, int host_choice);

/******************************************************************/

int main(int argc, char *argv[])
{
  int doors[3];
  int answer, i, j, door_choice, host_choice, final_choice, switch_door;
  int correct_count_stay = 0, correct_count_switch = 0, total_count_stay = 0, total_count_switch = 0;
  
  /* 0 is goat, 1 is car */
  for(i = 0; i < MAX_TRIALS; i++)
    {
      /* setup: three doors, a car behind one of the doors. */
      doors[0] = 0;
      doors[1] = 0;
      doors[2] = 0;
      answer = random() % 3; /* choose the location of car randomly. */
      doors[answer] = 1;

      door_choice = random() % 3; /* choose the door randomly. */
      
      /* Now choose the door the host opens in a random manner, 
       * but don't choose the one that includes the car. 
       * The door the host opens must NOT contain the right answer,
       * and must not be the same as the one one you chose. 
       */
      host_choice = choose_door_host_opens(answer, door_choice);
      
      /* now you can either stick to the current door or
       * switch to another door (which the host has not picked).  
       * do this randomly.
       */

      final_choice = -5;
      switch_door = random() % 2;
      if (switch_door == 0)
	{
	  total_count_stay++;
	  final_choice = door_choice;
	  if (final_choice == answer)
	    correct_count_stay++;
	}
      else
	{
	  total_count_switch++;
	  for(j = 0; j <= 2; j++)    
	    if ((j != door_choice) && (j != host_choice))
	      {
		final_choice = j;
	      }
	  if (final_choice == answer)
	    correct_count_switch++;
	}
    }

  printf("%s: number right stay: %d / %d | number right switched: %d / %d.\n", 
	 argv[0], correct_count_stay, total_count_stay, correct_count_switch, total_count_switch);
  printf("%s: fraction right for sticking with original door is %7.3f\n", 
	 argv[0], ((double) correct_count_stay) / ((double) total_count_stay));
  printf("%s: fraction right for changing the choice is %7.3f\n", 
	 argv[0], ((double) correct_count_switch) / ((double) total_count_switch));
  
  return 1;
}


/******************************************************************/

int choose_door_host_opens(int answer, int door_choice)
{
  /* These are the possibilities:
   * if the correct answer is door 0:
   *   if your pick is door 0, then host can open 1 or 2.
   *   if your pick is door 1, then host can open 2.
   *   if your pick is door 2, then host can open 1.
   * if the correct answer is door 1:
   *   if your pick is door 0, then host can open 2.
   *   if your pick is door 1, then host can open 0 or 2.
   *   if your pick is door 2, then host can open 0.
   * if the correct answer is door 2:
   *   if your pick is door 0, then host can open 1.
   *   if your pick is door 1, then host can open 0.
   *   if your pick is door 2, then host can open 0 or 1.
   */
  
  switch (answer)
    {
    case 0:
      if (door_choice == 0)
	return get_random(1, 2);
      if (door_choice == 1)
	return 2;
      if (door_choice == 2)
	return 1;
      break;
    case 1:
      if (door_choice == 0)
	return 2;
      if (door_choice == 1)
	return get_random(0, 2);
      if (door_choice == 2)
	return 0;
      break;
    case 2:
      if (door_choice == 0)
	return 1;
      if (door_choice == 1)
	return 0;
      if (door_choice == 2)
	return  get_random(0, 1);
      break;
    default:
      fprintf(stderr, "choose_door_host_opens(): unknown door number encountered!\n", answer);
      break;
    }

  fprintf(stderr, "choose_door_host_opens(): something's wrong!\n");
  return 0;
}

/******************************************************************/

int get_random(int val1, int val2)
{
  if ((random() % 2) == 1)
    return val2;
  else
    return val1;

  fprintf(stderr, "get_random(): something's wrong!\n");
  return 0;
}

/******************************************************************/

int get_door_choice(int current_choice, int host_choice)
{
  if ((current_choice == 0) && (host_choice == 1))
    return 2;
  if ((current_choice == 0) && (host_choice == 2))
    return 1;
  if ((current_choice == 1) && (host_choice == 0))
    return 2;
  if ((current_choice == 1) && (host_choice == 2))
    return 0;
  if ((current_choice == 2) && (host_choice == 0))
    return 1;
  if ((current_choice == 2) && (host_choice == 1))
    return 0;
  fprintf(stderr, "get_door_choice(): something's wrong!\n");
  return 0;
}

/******************************************************************/
