2012-03-10 46 views
0

我想学习Python库itertools,我认为一个好的测试将是模拟掷骰子。使用product并使用collections库计算可能的方式数量,可以很容易地生成所有可能的卷。我试图解决像Monopoly这样的游戏中出现的问题:当双打时,你再次掷出,最后的总和就是两次掷骰的总和。itertools骰子卷:双打滚两次

下面是我开始尝试解决这个问题:两个计数器,一个用于双打,另一个用于不打双打。我不确定是否有一种很好的方法来组合它们,或者如果两个计数器甚至是最好的方法。

我正在寻找一种使用itertools和集合来解决(通过枚举)掷骰子滚动问题的方法。

import numpy as np 
from collections import Counter 
from itertools import * 

die_n = 2 
max_num = 6 

die = np.arange(1,max_num+1) 
C0,C1 = Counter(), Counter() 

for roll in product(die,repeat=die_n): 
    if len(set(roll)) > 1: C0[sum(roll)] += 1 
    else: C1[sum(roll)] += 1 
+0

你能更正式地说出这个问题吗? – 2012-03-10 04:39:55

+0

@KarlKnechtel使用库itertools和集合枚举当'n'骰子从'1'到'm'顺序编号时出现的非标准化概率分布被滚动。除非所有骰子匹配,否则要计数的函数是“n”个骰子的总和。如果所有的骰子在第一卷上匹配,则计数的数字是第一卷和第二卷的总和。他们是否匹配在第二卷没关系。 带两个骰子的样本卷,编号为1..6:'[3,4],[2,1],[[4,4],[6,2]]'总数为[7,3, 16]'。 – Hooked 2012-03-10 04:47:49

+0

您可以考虑在蒙特卡洛式仿真中解决这个问题。 如果你在树形表示中考虑这个问题:从root开始,向depth = 1的子节点滚动一次,其中只有具有双精度的子节点具有相同结构的较深子节点的子树。这意味着那些双卷子的孩子回到根部。现在你有一个很好的结构,并且可以从根开始进行随机渲染以估计事件的概率。 – Mai 2013-10-20 00:13:44

回答

1

离开了numpy这里为简便起见:

首先,生成所有卷,无论是单人或双人卷:

from itertools import product 
from collections import Counter 

def enumerate_rolls(die_n=2, max_num=6): 
    for roll in product(range(1, max_num + 1), repeat=die_n): 
     if len(set(roll)) != 1: 
      yield roll 
     else: 
      for second_roll in product(range(1, max_num + 1), repeat=die_n): 
       yield roll + second_roll 

现在几个测试:

print(len(list(enumerate_rolls()))) # 36 + 6 * 36 - 6 = 246 
A = list(enumerate_rolls(5, 4)) 
print(len(A)) # 4 ** 5 + 4 * 4 ** 5 - 4 = 5116 
print(A[1020:1030]) # some double rolls (of five dice each!) and some single rolls 

和结果:

246 
5116 
[(1, 1, 1, 1, 1, 4, 4, 4, 4, 1), (1, 1, 1, 1, 1, 4, 4, 4, 4, 2), (1, 1, 1, 1, 1, 4, 4, 4, 4, 3), (1, 1, 1, 1, 1, 4, 4, 4, 4, 4), (1, 1, 1, 1, 2), (1, 1, 1, 1, 3), (1, 1, 1, 1, 4), (1, 1, 1, 2, 1), (1, 1, 1, 2, 2), (1, 1, 1, 2, 3)] 

要获得总计使用特殊Counter功能:

def total_counts(die_n=2, max_num=6): 
    return Counter(map(sum, enumerate_rolls(die_n, max_num))) 

print(total_counts()) 
print(total_counts(5, 4)) 

结果:

Counter({11: 18, 13: 18, 14: 18, 15: 18, 12: 17, 16: 17, 9: 16, 10: 16, 17: 16, 18: 14, 8: 13, 7: 12, 19: 12, 20: 9, 6: 8, 5: 6, 21: 6, 22: 4, 4: 3, 3: 2, 23: 2, 24: 1}) 
Counter({16: 205, 17: 205, 18: 205, 19: 205, 21: 205, 22: 205, 23: 205, 24: 205, 26: 205, 27: 205, 28: 205, 29: 205, 25: 204, 20: 203, 30: 203, 15: 202, 14: 200, 31: 200, 13: 190, 32: 190, 12: 170, 33: 170, 11: 140, 34: 140, 35: 102, 10: 101, 9: 65, 36: 65, 8: 35, 37: 35, 7: 15, 38: 15, 6: 5, 39: 5, 40: 1}) 

注:在这一点上,没有计算的概率方法总计。你必须知道它是双卷还是总卷才能正确称重。