python 这对蒙蒂霍尔来说是好还是坏的“模拟”?怎么来的?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1247863/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is this a good or bad 'simulation' for Monty Hall? How come?
提问by Josh Hunt
Through trying to explain the Monty Hall problemto 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:
通过昨天在课堂上向朋友解释蒙蒂霍尔问题,我们最终用 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"
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?
你能想出一个更好的版本吗?
回答by Alex Martelli
Your solution is fine, but if you want a stricter simulation of the problem as posed (and somewhat higher-quality Python;-), try:
您的解决方案很好,但是如果您想对所提出的问题进行更严格的模拟(以及更高质量的 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
a typical output is:
典型的输出是:
Changing has 66721 wins and 33279 losses
IOW, by changing you win 66.7% of the time
回答by si28719e
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
回答by Ronnie Overby
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.
在我偶然发现这个问题之前,我没有听说过蒙蒂霍尔问题。我觉得它很有趣,所以我阅读了它并创建了 ac# 模拟。这有点愚蠢,因为它模拟了游戏节目而不仅仅是问题。
I published the source and release on codeplex:
我在codeplex上发布了源代码和版本:
回答by peedurrr
Here's my version ...
这是我的版本...
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)) + '%'
回答by thedayturns
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..
你提到所有的选择都是硬编码的。但是如果你仔细观察,你会发现你认为的“选择”实际上根本不是选择。蒙蒂的决定不失一般性,因为他总是选择后面有山羊的门。你的交换总是由蒙蒂的选择决定,因为蒙蒂的“选择”实际上不是一个选择,你也不是。您的模拟给出了正确的结果..
回答by Tard
Not mine sample
不是我的样品
# -*- 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
回答by user1965074
I found this to be the most intuitive way of solving the problem.
我发现这是解决问题的最直观的方法。
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)
This outputs something like
这输出类似
If the participant knows_bayes she wins 66 % of the time.
If the participant does NOT knows_bayes she wins 33 % of the time.
回答by user2490950
Read a chapter about the famous Monty Hall problem today. This is my solution.
今天阅读有关著名的蒙蒂霍尔问题的一章。这是我的解决方案。
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()
回答by Velimir Mlaker
Yet another "proof," this time with Python 3. Note the use of generators to select 1) which door Monty opens, and 2) which door the player switches to.
另一个“证明”,这次是使用 Python 3。注意使用生成器来选择 1)Monty 打开哪扇门,以及 2)玩家切换到哪扇门。
import random
items = ['goat', 'goat', 'car']
num_trials = 100000
num_wins = 0
for trial in range(num_trials):
random.shuffle(items)
player = random.randrange(3)
monty = next(i for i, v in enumerate(items) if i != player and v != 'car')
player = next(x for x in range(3) if x not in (player, monty))
if items[player] == 'car':
num_wins += 1
print('{}/{} = {}'.format(num_wins, num_trials, num_wins / num_trials))
回答by Arnaldo P. Figueira Figueira
My solution with list comprehension to simulate the problem
我用列表理解来模拟问题的解决方案
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))
print simulate(N)
打印模拟(N)