views:

682

answers:

6
+10  Q: 

Monty Hall Problem

Through trying to explain the Monty Hall problem to a friend during class yesterday, we ended up coding it in Python to prove that if you always swap, you will win 2/3 times. We came up with this:

import random as r

#iterations = int(raw_input("How many iterations? >> "))
iterations = 100000

doors = ["goat", "goat", "car"]
wins = 0.0
looses = 0.0

for i in range(iterations):
 n = r.randrange(0,3)

 choice = doors[n]
 if n == 0:
  #print "You chose door 1."
  #print "Monty opens door 2. There is a goat behind this door."
  #print "You swapped to door 3."
  wins += 1
  #print "You won a " + doors[2] + "\n"
 elif n == 1:
  #print "You chose door 2."
  #print "Monty opens door 1. There is a goat behind this door."
  #print "You swapped to door 3."
  wins += 1
  #print "You won a " + doors[2] + "\n"
 elif n == 2:
  #print "You chose door 3."
  #print "Monty opens door 2. There is a goat behind this door."
  #print "You swapped to door 1."
  looses += 1
  #print "You won a " + doors[0] + "\n"
 else:
  print "You screwed up"

percentage = (wins/iterations) * 100
print "Wins: " + str(wins)
print "Looses: " + str(looses)
print "You won " + str(percentage) + "% of the time"

My friend thought this was a good way of going about it (and is a good simulation for it), but I have my doubts and concerns. Is it actually random enough?

The problem I have with it is that the all choices are kind of hard coded in.

Is this a good or bad 'simulation' for the Monty Hall problem? How come?

Can you come up with a better version?

A: 

Monty never opens the door with the car - that's the whole point of the show (he isn't your friend an has knowledge of what is behind each door)

Martin Beckett
Frickin' Monty! What a jerk.
zombat
No--he never opens the door with the car!
Loren Pechtel
Sorry it's normally state the other way around - the important point (that is lost on most people using this in interviews) is that Monty isn't picking at ranom
Martin Beckett
even though it's a bit irrelevant to the question, I have always been bothered by this problem. The reason the results may be "surprising" is only because most people misunderstand the rules. Monty is eliminating a bad option because he knows the answer. If you can see that, then this problem isn't so interesting anymore. The problem is mostly in understanding its own rules, not understanding probability.
tenfour
+1  A: 

You mentioned that all the choices are hardcoded in. But if you look closer, you'll notice that what you think are 'choices' are actually not choices at all. Monty's decision is without loss of generality since he always chooses the door with the goat behind it. Your swapping is always determined by what Monty chooses, and since Monty's "choice" was actually not a choice, neither is yours. Your simulation gives the correct results..

thedayturns
+23  A: 

Your solution is fine, but if you want a stricter simulation of the problem as posed (and somewhat higher-quality Python;-), try:

import random

iterations = 100000

doors = ["goat"] * 2 + ["car"]
change_wins = 0
change_loses = 0

for i in xrange(iterations):
    random.shuffle(doors)
    # you pick door n:
    n = random.randrange(3)
    # monty picks door k, k!=n and doors[k]!="car"
    sequence = range(3)
    random.shuffle(sequence)
    for k in sequence:
        if k == n or doors[k] == "car":
            continue
    # now if you change, you lose iff doors[n]=="car"
    if doors[n] == "car":
        change_loses += 1
    else:
        change_wins += 1

print "Changing has %s wins and %s losses" % (change_wins, change_loses)
perc = (100.0 * change_wins) / (change_wins + change_loses)
print "IOW, by changing you win %.1f%% of the time" % perc

a typical output is:

Changing has 66721 wins and 33279 losses
IOW, by changing you win 66.7% of the time
Alex Martelli
I am not sure I understand why you have the for k in sequence part? You don't even select a k, and it doesn't matter which door monty picks... all that matters is "n", right?
Tom
@Tom, I'm simply trying to simulate the classical Monty Hall Problem statement very faithfully -- Monty picks a door (different from your original pick and not the one w/the car) and you either change or you don't. Yep, Monty's move within the given constraints is irrelevant (as shown by the fact that k doesn't appear in the tail of the loop;-), so that whole block might be removed, EXCEPT that the whole point of the executable pseudocode it presumably to help convince skeptics, so, the closer we stick to the letter of the problem, the better!-)
Alex Martelli
@Alex: ok, just checking :-). nice answer, +1.
Tom
Wow. Fantastic response. Thanks!
joshhunt
@Tom, excellent observation actually, thanks! @joshhunt, always happy to help, just remember to accept it (that's the core etiquette of stack overflow!-) if and when you decide this answer was the most helpful one to your question.
Alex Martelli
@Alex: you might be interested in reading my comments on Mitch Wheat's post :-). I attempt to explain why monty hall is intuitive.
Tom
@Tom, good try, but the rage against Marylin vos Savant when SHE gave the right answer -- including math PhDs railing against her -- proves empirically but irrefutably that "intuitive" is NOT a correct word to describe the interaction between probabilities and the human brain!-)
Alex Martelli
@Alex: Maybe intuitive was the wrong word... but I think it's a good way of explaining why it works out the way it does... without showing anyone a formula or a simulation. I've used this way of explaining it to people (using 100, 1000, or even 10^6 doors), and they seem to get it. But yes, it did indeed baffle many people, and I certainly didn't get it the first time I saw the problem... but it's nice to visit a problem after knowing the answer and come up with a simpler explanation - which is what I was trying to do.
Tom
@Tom, sure, but showing a precise, detailed simulation is one more way to help convince somebody THAT it works (while reasoning is better to show WHY it works;). I've met similar issues in the past, e.g. convincing bridge players about "restricted choice" (which follows very directly from Bayes' formula, actually;-).
Alex Martelli
+1  A: 

I like something like this.


#!/usr/bin/python                                                                                                            
import random
CAR   = 1
GOAT  = 0

def one_trial( doors, switch=False ):
    """One trial of the Monty Hall contest."""

    random.shuffle( doors )
    first_choice = doors.pop( )
    if switch==False:
        return first_choice
    elif doors.__contains__(CAR):
        return CAR
    else:
        return GOAT


def n_trials( switch=False, n=10 ):
    """Play the game N times and return some stats."""
    wins = 0
    for n in xrange(n):
        doors = [CAR, GOAT, GOAT]
        wins += one_trial( doors, switch=switch )

    print "won:", wins, "lost:", (n-wins), "avg:", (float(wins)/float(n))


if __name__=="__main__":
    import sys
    n_trials( switch=eval(sys.argv[1]), n=int(sys.argv[2]) )

$ ./montyhall.py True 10000
won: 6744 lost: 3255 avg: 0.674467446745
blackkettle
A: 

Here is an interactive version:

from random import shuffle, choice
cars,goats,iters= 0, 0, 100
for i in range(iters):
    doors = ['goat A', 'goat B', 'car']
    shuffle(doors)
    moderator_door = 'car'
    #Turn 1:
    selected_door = choice(doors)
    print selected_door
    doors.remove(selected_door)
    print 'You have selected a door with an unknown object'
    #Turn 2:
    while moderator_door == 'car':
        moderator_door = choice(doors)
    doors.remove(moderator_door)
    print 'Moderator has opened a door with ', moderator_door
    #Turn 3:
    decision=raw_input('Wanna change your door? [yn]')
    if decision=='y':
        prise = doors[0]
        print 'You have a door with ', prise
    elif decision=='n':
        prise = selected_door
        print 'You have a door with ', prise
    else:
        prise = 'ERROR'
        iters += 1
        print 'ERROR:unknown command'
    if prise == 'car':
        cars += 1
    elif prise != 'ERROR':
        goats += 1
print '==============================='
print '          RESULTS              '
print '==============================='
print 'Goats:', goats
print 'Cars :', cars
psihodelia
+1  A: 

I hadn't heard of the Monty Hall Problem before I stumbled across this question. I thought it was interesting, so I read about it and created a c# simulation. It's kind of goofy since it simulates the game-show and not just the problem.

I published the source and release on codeplex:

http://montyhall.codeplex.com

Ronnie Overby