Logic solving Monty Hall problem?

One of the programming projects in my C++ book has me working on a simulation of the Monty Hall problem (http://en.wikipedia.org/wiki/Monty_Hall_problem).

My attempt is below. It gives results roughly what I'd expect to see (that you're better off switching than not) but I'm almost 100% sure my logic is wrong somehow, I just don't know how.

Can someone help? Cheers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/*You are a contestant on a game show and have won a shot at the grand prize.
Before you are three doors. $1,000,000 in cash has randomly been placed behind
one door. Behind the other two doors are the consolation prizes of dishwasher
detergent. The game show host asks you to select a door, and you randomly pick
one. However, before revealing the prize behind your door, the game show host
reveals one of the other doors that contains a consolation prize. At this point, the
game show host asks if you would like to stick with your original choice or to
switch to the remaining door.

Write a function to simulate the game show problem. Your function should
randomly select locations for the prizes, select a door at random chosen by the
contestant, and then determine whether the contestant would win or lose by
sticking with the original choice or switching to the remaining door. You may
wish to create additional functions invoked by this function.

Next, modify your program so that it simulates playing 10,000 games. Count
the number of times the contestant wins when switching vs. staying. If you are
the contestant, what choice should you make to optimize your chances of
winning the cash, or does it not matter?*/

#include <iostream>
#include <cstdlib>
#include <ctime>

int selectDoor();

using std::cout;
using std::endl;

int main()
{
	int playerDoor, winCount = 0, loseCount = 0, gameCount = 0, winningDoor;
	
	srand(time(NULL)); //set a different seed for rand() every time to get different game outputs
	
	do
	{
		winningDoor = selectDoor(); //get a door number that contains the million bucks
		playerDoor = selectDoor(); //get a door number that the player has chosen
	
		if(winningDoor != 1 && playerDoor != 1)
		{
			if(playerDoor == winningDoor) winCount++;
			else loseCount++;
			continue;
		}
		if(winningDoor != 2 && playerDoor != 2)
		{
			if(playerDoor == winningDoor) winCount++;
			else loseCount++;
			continue;
		}
		if(winningDoor != 3 && playerDoor != 3)
		{
			if(playerDoor == winningDoor) winCount++;
			else loseCount++;
			continue;
		}
	
		gameCount++;
	}
	while(gameCount < 10000);
	
	cout << "You won " << winCount << " times by not switching." << endl;
	cout << "You won " << loseCount << " times by switching." << endl;
		
	return 0;
}

int selectDoor()
{
	return (rand() % 3) + 1; //call to rand() returns 0-2, + 1 to give range 1-3, best way to avoid impossible choice of 0
}
Last edited on
Does this return output for you?

The continue statements should skip the iteration of the loop on every loop as the program will always enter one of the if statements, and will never update the gameCount variable which is needed to reach the end of the loop - causing an infinite loop!

http://www.cplusplus.com/doc/tutorial/control/


Some aspects of the program are missing - like the revealing of the door and then the program choosing whether to stick to the original choice or change to the other door.
As stated, it give an output roughly what I'd expect as an answer to the Monty Hall problem, as in it says I'd win approx 3000 games by not switching and approx 6000 by switching.

Every time I run the code above I get an answer of between 3000 and 3500 for the first cout statement and between 6000 and 6500 for the second.
I don't know what you mean by you think your logic is wrong. Your code doesn't have any logic. Its barely got any code at all.

If you meant to say you disagree with the logic of the results, I'll admit I am quite skeptic myself. You are best to be reminded that rand() is NOT a random number generator, but rather a pseudo random number generator. It is reportedly close enough to RANDOMNESS, as is needed by some simple programs.

Suppose a contestant is on the game show, and he's daydream fantacizing about the new cout he hopes he's about to win, and pays no attention to the instructions, chooses door #1 and when he's presented with a goat behind door #3 gets pissed cusses at the host and walks off. Then the host decides to pick a new contestent from the audience to continue where the former contestant left off, but this contestant came in late to the show and has also never seen it before. He didn't here the instructions either, he may see see a goat standing on the stage, but pays no attention, as far as he is concerned this only has two possible options, choose door 1, or choose door 2. Yes if he chooses door #2 (the same door the originial contestant would have choosen if he had decided to switch), he will have a 50% chance of winning, but he'll also have a 50% chance of winning if he switched door #1, the same the other had picked in the first place.

Regardless of what you think of this classic paradox the code is below:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include <stdio.h>
#include <cstdlib>
#include <time.h>
#include "after.h"
#include "open.h"

using namespace std;
string s1, s2, s3, s4, s5, str, s1a, s2a, s3a, s4a, s5a, str2;

int reveal_non_chosen_loser(const int & winner);
int decide_non_chosen_loser(const int & winner, const int & chosen);
int higher(const int & a, const int & b);
int lower(const int & a, const int & b);

int wins, times; double percentage_won; char jazz = 'y';
bool first = true;
char x[1000]; char y[1000];

int game()
{
    int door = rand() % 3 + 1;
    ++times;
    //printf("Door = %d", door); printf("\n");
    int choice;
    if (first) { first = false; printf("Hello\nAnd Welcome\n"); }
    printf("Please choose a door: 1, 2 or 3.\nIf you choose correctly you will win.\n");
    scanf("%d", &choice);
    printf("You choose DOOR #%d %s", choice, "\n");
    int non_chosen_loser = decide_non_chosen_loser(door, choice);
    decide_non_chosen_loser(door, choice);
    printf("Lets have a look at whats behind door #%d", non_chosen_loser); printf(" shall we? \n");//, non_chosen_loser);
    int sw = rand() % 5; switch(sw){case 1: str = s1; str2 = s1a; break; case 2: str = s2; str2 = s2a; break; case 3: str = s3; str2 = s3a; break; case 4: str = s4; str2 = s4a; break; case 5: str = s5; str2 = s5a; break;    default: break; }
    char tch [1000];
    assign (str, tch);
    printf("%s", tch);
    printf("\nDo you want to switch to door #%d, or do you feel lucky today? \n", decide_non_chosen_loser(non_chosen_loser, choice));
    printf("Y/N\n");
    char jas;
    scanf("%d", &jas);
    if (jas == 'y' || jas == 'Y')
        choice = decide_non_chosen_loser(choice, non_chosen_loser);
    if (choice == door)
        {
            ++wins;
            printf("You win!!!!!!!!!\n");
        }
    else {  printf("!!!!You lose.\n");
            int itch = (sw + (rand() % 4) ) % 5 + 1;
            switch(itch) { case 1: str = s1; str2 = s1a; break; case 2: str = s2; str2 = s2a; break; case 3: str = s3; str2 = s3a; break; case 4: str = s4; str2 = s4a; break; case 5: str = s5; str2 = s5a; break;    default: break; }
            assign (str, x); assign (str2, y);
            printf("But don't worry you've still won a ");
            printf("\n%s%s", x, y );
            printf("     ");
            printf("\n");
    }
    return false;
}

int main()
{
    open window;
    srand(time(NULL));
    s1 = "A pile of cow dung. "; s2 = "A goat."; s3 = "A blank sheet of paper.  "; s4 = "Absolutely Nothing.  "; s5 = "A box.  ";
    s1a = "Ya know, manure makes excellent fertilizer. \n";
    s2a = "They are anything but pickey eaters and can be kept as a pet, if you want. \n";
    s3a = "You can write on it, or use it as spare firewood if you need to. \n";
    s4a = "Better luck next time. \n";
    s5a = "Maybe there's something in it. You never know. \n";
    bool again = false;
    do
    {
        game();
        printf("Do you want to play again? Y/N ");
        printf("\n");
        scanf("%c", &jazz);
        scanf("%c", &jazz);
        scanf("%c", &jazz);
        if (jazz == 'Y' || jazz == 'y')
            again = true;
        else again = false;
    }while (again);
    percentage_won = (double)wins / (double)times;
    printf("wins = %d", wins); printf(" times = %d", times);
    printf("\nYou winning percentage = %d", percentage_won);


    return 0;
}

int decide_non_chosen_loser(const int & winner, const int & chosen)
{
    int loser, temp = rand() % 2;
    if (winner != chosen)
        loser = (3 - (higher(winner, chosen) + lower(winner, chosen) ) % 3);
    else loser = ( ( (winner + temp) % 3) + 1);
    return loser;
}

int higher(const int &a, const int & b)
{
    if (a > b)
        return a;
    else return b;
}

int lower(const int & a, const int & b)
{
    if (a > b)
        return b;
    else return a;
}


To make it conform to your assignment requirements changes a few lines here and there, the while loop to while (times < 10000) for example, remove the scanfs prompting for input to repeat the program and to choose the door, etc etc...
The logic of switching the doors to improve your chances is correct but you have to take into account the fact that Monty KNOWS where the million dollars is hiding. You'll have to model that fact into your code as well. It's not just random.
Topic archived. No new replies allowed.