2013-05-07 69 views
0

我處於統計類,並且我們經常因各種限制而給出「骰子問題」。這是一個概率問題,我需要通過使用蒙特卡羅方法來評估事件的概率。我知道我可以通過它整合我的方式,但我想編寫一個程序,使我可以簡單地修改約束條件,包括我有多少個骰子,多少個骰子以及這些骰子有多少個邊。使用蒙特卡羅方法在Python 3.2中查找某個特定骰子輸出的特定概率

這是我正在處理的問題之一。更簡單,因爲我不想被我的代碼寫成「能力」。

假設一個骰子各有9個邊。估計當你滾動5個骰子時至少有3個骰子的概率相同。

這是我們給出的問題的一般模板: 滾動X個n邊的骰子,每個骰子的邊數從1到n。估計我們得到3個或更多骰子的概率,結果相同。

我想爲樣本問題編寫一個函數,假設這需要輸入一個整數n,它是每個骰子中的面數,並計算出3個或更多骰子具有相同值的概率。我最大的問題是約束「至少5分之3」。 我查看了Stackoverflow上的其他類似問題,但沒有一個真正觸及我的基礎。你將如何編寫約束代碼? 我正在使用Python 3.2。

class Die(object): 
    def __init__(self, sides = 9): 
    self.sides = sides 

    def roll(self): 
    return randint(1, self.sides) 

我被困在這裏。任何輸入是有幫助的,謝謝!

+0

@MartijnPieters真的嗎?但是,我還能如何確保擲骰子是公平和獨立的? – user2227808 2013-05-07 13:12:45

+0

啊,現在我真的應該把我的腳從我的嘴裏拿出來,讀一下蒙特卡洛方法*先*。我的道歉,這是你*擲骰子的方法之一。 :-P – 2013-05-07 13:19:41

回答

2

我不認爲我會在這裏使用課堂。你只需生成骰子卷,然後檢查骰子卷是否應該計數。在這種情況下,我會使用一個Counter做計數只是爲了讓代碼更乾淨:

from collections import Counter 
from random import randint 

def roll(ndice,nsides=9): 
    return [randint(1,nsides) for _ in range(ndice)] 

def count_it(): 
    c = Counter(roll(5)) 
    return c.most_common(1)[0][1] >= 3 

ntries = 100000 
print (sum(1 for _ in range(ntries) if count_it())/ntries) 

它看起來像你對我有大約10%的機率。蒙特卡洛的訣竅在於確定您是否已經收斂。您可以使用ntries的不同號碼進行幾次操作。您製作的產品越大ntries,您的輸出中的點差就越小。最終,當傳播足夠小時,你說你已經有一些確定的解決方案。

+0

感謝您的幫助!但是,您是否介意通過ntries解釋您的意思?這是指我製作的卷數量?我看到你的觀點,就像我獲得的更好的平均數越多,但在技術上我認爲我只做1卷。那會是1嘗試嗎? – user2227808 2013-05-07 14:01:13

+0

@ user2227808 - 你不能從1嘗試任何東西。蒙特卡羅方法的基礎是,你反覆嘗試,並從實際做實驗中獲得概率。所以是的,'ntries'是您的計算機正在滾動5個9面骰子的次數。 – mgilson 2013-05-07 14:23:15

0

只需使用模具類大量的時間:

# roll a lot of dice! 
myDie = Die(9) # 9 sides 

roll_counts = {side:0 for side in range(1, myDie.sides + 1)} 

numRolls = int(1e6) 
for x in xrange(numRolls): 
    roll_counts[myDie.roll()] += 1 

然後根據需要分析你的發行版:

for side in sorted(roll_counts): 
    side_pct = float(roll_counts[side])/numRolls * 100 
    print 'side {} comprised {}% of all rolls'.format(side, side_pct) 

編輯:我知道這個解決方案沒有解決你的功課問題,但希望它能爲您提供所需的工具,用於擲骰和計數骰子。很可能你需要一次完成多人死亡並且有一種比較他們在每次擲骰時的平等的方法。