试图用Python解决Monty Hall

时间:2014-09-09 23:10:20

标签: python numpy

我正在尝试理解Monty Hall问题的这个解决方案,我理解大部分代码,但我被困在两个部分。

以下是代码,但具体来说我坚持这两部分

result[bad] = np.random.randint(0,3, bad.sum())

以及整个switch_guess函数。

如果有人能用简单的英语向我解释这将是非常棒的。

#Simulates picking a prize door
def simulate_prizedoor(nsim):
    return np.random.randint(0,3,(nsim))

#Simulates the doors guessed
def simulate_guesses(nsim):
    return np.zeros(nsim, dtype=np.int)

#Simulates the "game host" showing whats behind a door
def goat_door(prize_doors, guesses):
    result = np.random.randint(0,3, prize_doors.size)
    while True:
        bad = (result == prize_doors) | (result == guesses)
        if not bad.any():
            return result
    result[bad] = np.random.randint(0,3, bad.sum())

#Used to change your guess
def switch_guess(guesses, goat_doors):
    result = np.zeros(guesses.size)
    switch = {(0, 1): 2, (0, 2): 1, (1, 0): 2, (1, 2): 1, (2, 0): 1, (2, 1): 0}
    for i in [0,1,2]:
        #print "i = ", i
        for j in [0,1,2]:
            #print "j = ", j
            mask = (guesses == i) & (goat_doors == j)
            #print "mask = ", mask
            if not mask.any():
                continue
            result = np.where(mask, np.ones_like(result) * switch[(i, j)], result)
    return result

#Calculates the win percentage
def win_percentage(guesses, prizedoors):
    return 100 * (guesses == prizedoors).mean()

#The code to pull everything together
nsim = 10000

#keep guesses
print "Win percentage when keeping original door"
print win_percentage(simulate_prizedoor(nsim), simulate_guesses(nsim))

#switch
pd = simulate_prizedoor(nsim)
guess = simulate_guesses(nsim)
goats = goat_door(pd, guess)
guess = switch_guess(guess, goats)
print "Win percentage when switching doors"
print win_percentage(pd, guess)

2 个答案:

答案 0 :(得分:2)

  

...特别是我坚持这两部分

result[bad] = np.random.randint(0,3, bad.sum())

让我们把它分解成碎片。将10000缩小到较小的值可能会有所帮助,例如5,这样您就可以打印出值(使用print调用,或者在调试器中)并查看'继续。

当我们启动此功能时,prize_doors将有02的5个随机值,如2 2 0 1 2,而guesses将有5个值,全部为0,如0 0 0 0 0。因此,result将从0到2的5个随机值开始,例如0 2 2 0 1

每次第一次循环,bad将是5个bool值的列表,如果True中的对应值与相应的值匹配,则每个值resultprize_doorsguesses中。因此,在此示例中,True True False True False,因为猜测#1与prize_doors匹配,并且猜测#0和#3匹配goats

不幸的是,我们只是永远绕过那个循环,因为循环中没有任何内容可以修改result,因此bad将会是相同的永远,永远做同样的检查总是会返回相同的值。


但是如果你缩进result[bad] = …行,那么它就会在循环中缩进,这会改变一切。所以,让我们假设你应该做的是什么,而你只是把它复制错了。

当被视为数字时,TrueFalse分别具有值10。因此,bad.sum()bad中有多少匹配的计数 - 在这种情况下,3

因此,np.random.randint(0, 3, bad.sum())02选择3个随机值,让我们说1 0 1

现在,result[bad]选择resultbad的相应值为True的所有元素,因此在此示例中为result[0]result[1]result[3]

因此,我们最终将1 0 1分配给这三个选定的位置,因此result现在为1 0 2 1 1

因此,下次循环时,bad现在为True False False False False。我们仍然至少有一个True值,因此我们再次运行result[bad] =行。这一次,bad.sum()1,因此我们选择1个随机值,让我们说0,然后我们将该值分配给result[0],所以{ {1}}现在是result

下一次,0 0 2 1 1现在是bad,因此False False False False Falsebad.any(),所以我们已经完成了。

换句话说,每次通过时,我们都会采用与奖品门或山羊门不匹配的所有价值,并为他们选择一扇新门,直到最后没有这样的价值。

答案 1 :(得分:0)

它也使我感到困惑,直到5分钟前我终于明白了。 由于第一个问题已经解决,我只谈第二个问题。

直觉是这样的:给定一系列(猜测,山羊门),在(i,j)循环中,总有一些模拟(例如,模拟[0]和模拟[5])'命中'通过(i,j),即说法,第0和第5次模拟猜测我和山羊门j。

此示例中的变量mask记录0和5。然后可以确定第0和第5的结果,因为在这些模拟中,切换到的唯一可能的门由i和j确定。因此,np.where刷新会导致这些模拟,保持其他模拟不变。

直觉就在上面。如果你想知道我在说什么,你需要知道np.where如何工作。祝你好运。