Это хороший или плохой «симулятор» для Монти Холла? Как так? - PullRequest
17 голосов
/ 08 августа 2009

Вчера, пытаясь объяснить проблему Монти Холла другу во время урока, мы закончили писать код на Python, чтобы доказать, что если вы всегда поменяетесь местами, вы выиграете 2/3 раза. Мы придумали это:

import random as r

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

doors = ["goat", "goat", "car"]
wins = 0.0
losses = 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."
        losses += 1
        #print "You won a " + doors[0] + "\n"
    else:
        print "You screwed up"

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

Мой друг подумал, что это хороший способ (и хороший симулятор), но у меня есть свои сомнения и опасения. Это на самом деле достаточно случайно?

Проблема, с которой я столкнулся, заключается в том, что все варианты жестко запрограммированы.

Это хороший или плохой «симулятор» для проблемы Монти Холла? Как получилось?

Можете ли вы придумать лучшую версию?

Ответы [ 17 ]

37 голосов
/ 08 августа 2009

Ваше решение в порядке, но если вы хотите более жесткое моделирование поставленной задачи (и несколько более качественный Python ;-), попробуйте:

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

типичный вывод:

Changing has 66721 wins and 33279 losses
IOW, by changing you win 66.7% of the time
2 голосов
/ 20 апреля 2015

Вот моя версия ...

import random

wins = 0

for n in range(1000):

    doors = [1, 2, 3]

    carDoor     = random.choice(doors)
    playerDoor  = random.choice(doors)
    hostDoor    = random.choice(list(set(doors) - set([carDoor, playerDoor])))

    # To stick, just comment out the next line.
    (playerDoor, ) = set(doors) - set([playerDoor, hostDoor]) # Player swaps doors.

    if playerDoor == carDoor:
        wins += 1

print str(round(wins / float(n) * 100, 2)) + '%'
2 голосов
/ 08 августа 2009

Вы упомянули, что все варианты жестко запрограммированы. Но если вы присмотритесь, вы заметите, что то, что вы считаете «выбором», на самом деле вовсе не является выбором. Решение Монти без потери общности, так как он всегда выбирает дверь с козой за ним. Ваш обмен всегда определяется тем, что выберет Монти, и, поскольку «выбор» Монти на самом деле не был выбором, ни ваш. Ваше моделирование дает правильные результаты ..

2 голосов
/ 09 сентября 2010

Я не слышал о проблеме Монти Холла, пока не наткнулся на этот вопрос. Я думал, что это было интересно, поэтому я прочитал об этом и создал симуляцию c #. Это немного глупо, поскольку имитирует игровое шоу, а не только проблему.

Я опубликовал исходный код и релиз на codeplex:

http://montyhall.codeplex.com

2 голосов
/ 08 августа 2009

Мне нравится что-то вроде этого.


#!/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
1 голос
/ 17 мая 2016

Прочтите главу о знаменитой проблеме Монти Холла сегодня. Это моё решение.

import random

def one_round():
    doors = [1,1,0] # 1==goat, 0=car
    random.shuffle(doors) # shuffle doors
    choice = random.randint(0,2) 
    return doors[choice] 
    #If a goat is chosen, it means the player loses if he/she does not change.
    #This method returns if the player wins or loses if he/she changes. win = 1, lose = 0

def hall():
    change_wins = 0
    N = 10000
    for index in range(0,N):
        change_wins +=  one_round()
    print change_wins

hall()
1 голос
/ 19 июня 2015

Я считаю, что это наиболее интуитивный способ решения проблемы.

import random

# game_show will return True/False if the participant wins/loses the car:
def game_show(knows_bayes):

    doors = [i for i in range(3)]

    # Let the car be behind this door
    car = random.choice(doors)

    # The participant chooses this door..
    choice = random.choice(doors)

    # ..so the host opens another (random) door with no car behind it
    open_door = random.choice([i for i in doors if i not in [car, choice]])

    # If the participant knows_bayes she will switch doors now
    if knows_bayes:
        choice = [i for i in doors if i not in [choice, open_door]][0]

    # Did the participant win a car?
    if choice == car:
        return True
    else:
        return False

# Let us run the game_show() for two participants. One knows_bayes and the other does not.
wins = [0, 0]
runs = 100000
for x in range(0, runs):
    if game_show(True):
        wins[0] += 1
    if game_show(False):
        wins[1] += 1

print "If the participant knows_bayes she wins %d %% of the time." % (float(wins[0])/runs*100)
print "If the participant does NOT knows_bayes she wins %d %% of the time." % (float(wins[1])/runs*100)

Это выводит что-то вроде

If the participant knows_bayes she wins 66 % of the time.
If the participant does NOT knows_bayes she wins 33 % of the time.
1 голос
/ 09 сентября 2013

Не мой образец

# -*- coding: utf-8 -*-
#!/usr/bin/python -Ou
# Written by kocmuk.ru, 2008
import random

num = 10000  # number of games to play
win = 0      # init win count if donot change our first choice

for i in range(1, num):                            # play "num" games
    if random.randint(1,3) == random.randint(1,3): # if win at first choice 
        win +=1                                    # increasing win count

print "I donot change first choice and win:", win, " games"   
print "I change initial choice and win:", num-win, " games" # looses of "not_change_first_choice are wins if changing
1 голос
/ 06 августа 2012

Мое решение с пониманием списка для имитации проблемы

from random import randint

N = 1000

def simulate(N):

    car_gate=[randint(1,3) for x in range(N)]
    gate_sel=[randint(1,3) for x in range(N)]

    score = sum([True if car_gate[i] == gate_sel[i] or ([posible_gate for posible_gate in [1,2,3] if posible_gate != gate_sel[i]][randint(0,1)] == car_gate[i]) else False for i in range(N)])

    return 'you win %s of the time when you change your selection.' % (float(score) / float(N))

печать симуляции (N)

1 голос
/ 01 сентября 2010

Вот интерактивная версия:

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