user1777667 - 1 year ago 60

Python Question

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%?

Answer Source

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
```