user1777667 - 1 year ago 85
Python Question

# Python OOP Monty Hall not giving the expected results

Trying out some OOP in python, I tried to create a Monty Hall Problem simulation that is giving odd results. I implement three different strategies that a player can choose from, either to stay with the first door selected, switch to the second closed door, or randomly choose between them.

``````import random

class Door():
behind    = None
is_open   = False
is_chosen = False
def __init__(self,name=None):
self.name = name
def open(self):
self.is_open = True
def choose(self):
self.is_chosen = True

class Goat():
is_a = 'goat'

class Car():
is_a = 'car'

class Player():
door = None
def choose(self,door):
self.door = door
self.door.choose()
def open(self):
self.door.open()
if self.door.behind.is_a == 'car':
return True
return False

def play(strategy):
player = Player()
items = [Goat(),Goat(),Car()]
doors = [Door(name='a'),Door(name='b'),Door(name='c')]
for door in doors:
item = items.pop()
door.behind = item
random.shuffle(doors)
player.choose(random.choice(doors))
if strategy == 'random':
if random.choice([True,False]):
for door in doors:
if not door.is_open and not door.is_chosen:
final = door
break
else:
final = player.door
elif strategy == 'switch':
for door in doors:
if not door.is_open and not door.is_chosen:
final = door
break
elif strategy == 'stay':
final = player.door
player.choose(final)
if player.open():
return True
else:
return False

## Play some games
for strategy in ['random','switch','stay']:
results = []
for game in range(0,10000):
if play(strategy):
results.append(True)
else:
results.append(False)

## Gather the results
wins  = 0
loses = 0
for game in results:
if game:
wins += 1
else:
loses += 1
print 'results:\tstrategy={}\twins={}\tloses={}'.format(strategy,str(wins),str(loses))
``````

But every time I run it, I get something like:

``````results:        strategy=random wins=3369       loses=6631
results:        strategy=switch wins=3369       loses=6631
results:        strategy=stay   wins=3320       loses=6680
``````

Why is this giving nearly the same results for each strategy? Shouldn't the 'switch' strategy give a ratio of ~66% wins and 'stay' give ~33%?

You're not playing the game correctly. After the contestant chooses a door, the host reveals a goat behind one of the other two doors, and then offers the contestant the opportunity to switch -- you're allowing a choice between three doors instead of two. Here's a revised `play()` function:

``````def play(strategy):
player = Player()
items = [Goat(), Goat(), Car()]
doors = [Door(name='a'), Door(name='b'), Door(name='c')]

random.shuffle(items)

for door in doors:
item = items.pop()
door.behind = item

player.choose(random.choice(doors))

# player has chosen a door, now show a goat behind one of the other two

show = None
for door in doors:
if not (door.is_open or door.is_chosen) and door.behind.is_a == 'goat':
show = door
show.open()
break

# The player has now been shown a goat behind one of the two doors not chosen

if strategy == 'random':
if random.choice([True, False]):
for door in doors:
if not (door.is_open or door.is_chosen):
final = door
break
else:
final = player.door

elif strategy == 'switch':
for door in doors:
if not (door.is_open or door.is_chosen):
final = door
break

elif strategy == 'stay':
final = player.door

player.choose(final)

return player.open()
``````

That produces results like:

``````results:    strategy=random wins=4977   loses=5023
results:    strategy=switch wins=6592   loses=3408
results:    strategy=stay   wins=3368   loses=6632
``````
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download