【问题标题】:itertools dice rolls: doubles roll twiceitertools 骰子掷骰子:双倍掷骰子两次
【发布时间】:2012-03-10 01:39:55
【问题描述】:

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

以下是我解决问题的开始尝试:两个计数器,一个用于双打,另一个用于非双打。我不确定是否有将它们组合在一起的好方法,或者这两个计数器是否是最好的方法。

我正在寻找一种巧妙的方法来解决(通过枚举)使用 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

【问题讨论】:

  • 您能否更正式地说明一下这个问题?
  • @KarlKnechtel 使用库 itertools 和 collections 枚举从1m 顺序编号的n 骰子时出现的非标准化概率分布。要计数的函数是n 骰子的总和,除非所有骰子都匹配。如果所有骰子都在第一次掷骰上匹配,则计数的数字是第一次掷骰和第二次掷骰的总和。他们是否在第二卷上匹配并不重要。带有两个骰子的样本卷,编号为 1..6:[3,4], [2,1], [[4,4], [6,2]],总数为 [7,3,16]
  • 你可以考虑在蒙特卡洛风格的模拟中解决这个问题。如果您在树表示中考虑这个问题:从根开始,向深度 = 1 的孩子滚动一次,其中只有具有双精度的孩子具有相同结构的更深孩子的子树。这意味着那些双滚子指向根。现在你有了一个很好的结构,并且可以从根开始进行随机渲染来估计事件的概率。

标签: python algorithm itertools python-collections


【解决方案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})

注意:此时,无法计算总数的概率。您必须知道它是双卷还是全卷才能正确称重。

【讨论】:

    猜你喜欢
    • 2018-09-08
    • 1970-01-01
    • 2012-02-29
    • 2015-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多