微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

我正在尝试做一个程序来显示投掷 N 个骰子的样本空间

如何解决我正在尝试做一个程序来显示投掷 N 个骰子的样本空间

我正在尝试做一个程序,显示N 个骰子的样本空间并写入每个骰子的结果,然后将样本空间每个元素的每个骰子的结果相加,然后最后用总和制作直方图。

我知道如何处理少量骰子,手动放置 for 循环。

3 个骰子的示例:

import numpy as np
import matplotlib.pyplot as plt

diceNum=3       # number of dices
ss = 6**diceNum # number of elements of the sample space: throw n dices and write points of each dice. (n**N)

diceSum = []
diceThrow = []

nn=0 # to count the number of elements

# 3 for loops for each dice
for k in range(6):
   
   for i in range(6):
   
       for j in range(6):
           
           dices = [k+1,i+1,j+1]   # Result of throw the 3 dices
           diceThrow.append(dices) # Sample space 
           diceSum.append(sum(diceThrow[nn])) #Sum each element of the sample space
       
           nn=nn+1


print(diceThrow)
print(" ")
print(diceSum)

# Make a histogram with the sum of each element of the sample space
plt.hist(diceSum,bins = sm)
plt.grid()
plt.show()

我的问题是如何对 N 个骰子执行此操作,例如 N=100,而不需要手动放置 N for 个循环?对这个算法有什么想法吗?

解决方法

像比尔提到的那样制作更直观的代码:

diceNum=10     # number of dices
ss = 6**diceNum # number of elements of the sample space: throw n dices and write points of each dice. (n**N)

diceSum = []
diceThrow = []


def roll_dice(diceThrow_n1)->list: # diceThrow_n1 is the list for n dices thrown
    #check if it's the first dice
    if diceThrow_n1 == []:
        diceThrow_n2=np.array([[i] for i in range(1,7)])
    else:
        diceThrow_n2 = [] # list for n+1 thrown dices
        for d in diceThrow_n1:
            for t in range(1,7): # throw the n+1 dice
                diceThrow_n2.append([*d,t])
    return diceThrow_n2

for d in range(diceNum): # Throw diceNum dices
    diceThrow = roll_dice(diceThrow)

diceSum = [sum(elm) for elm in diceThrow] # Sum each element of the sample space

roll_dice 接受你的 diceThrown 列表,除了获取所有 List 条目并添加另一个掷骰子的结果之外,什么都不做。 (因此每次执行该函数时,diceThrow 中的条目都会乘以 6)。

让我们检查一下 diceNum = 2: 在第一次执行 d = 0(第一次掷骰子)时,我们提供了 roll_dice 一个空列表(diceThrow = [])。所以 roll_dice 用 1 ...6 填充 diceThrow(diceThrow = [[1],[2],[3],[4],[5],[6]])。 所以现在 d = 1: roll_dice 以 diceThrow = [[1],[6]] 开头: 所以我们转到函数的 else 部分。现在我们遍历列表中的所有条目。从 d = [1] 开始。 (* 在列表前面给出了所有元素 (*[a,b,c]=a,c)) 它取每一个掷骰子并将下一次掷骰的结果相加。所以 [1] 到 [[1,1],[1,2],3],...,6]]。但是 1 只是第一次抛出的一个可能结果,所以我们对所有其他可能的结果都这样做,并以:

diceThrow = [[1 1]
 [1 2]
 [1 3]
 [1 4]
 [1 5]
 [1 6]
 [2 1]
 [2 2]
 [2 3]
 [2 4]
 [2 5]
 [2 6]
 [3 1]
 [3 2]
 [3 3]
 [3 4]
 [3 5]
 [3 6]
 [4 1]
 [4 2]
 [4 3]
 [4 4]
 [4 5]
 [4 6]
 [5 1]
 [5 2]
 [5 3]
 [5 4]
 [5 5]
 [5 6]
 [6 1]
 [6 2]
 [6 3]
 [6 4]
 [6 5]
 [6 6]]

现在可以对每个额外的骰子重复此操作。 最后,我们像以前一样对每个条目进行总结,但是每次在 diceThrow 中创建新条目时都这样做,我们在最后这样做,以防止我们多次这样做。 但问题由此开始。这是非常低效的,因为python中的列表并不是最快的。我们一次又一次地这样做。创建一个列表,创建一个更大的列表,....

一种更好但不太直观的方法是使用 numpy。

diceNum=2
diceThrow = np.array(np.meshgrid(*([np.array([1,2,3,4,5,6])]*diceNum))).T.reshape(-1,diceNum)
diceSum = [sum(elm) for elm in diceThrow]

原则上你给meshgrid函数diceNum np.arrays 1,6],然后以你获得diceNum骰子的方式重塑它。 对这里发生的事情的一个很好的解释(对我 xD 有一点启发),你可以在这里找到 Numpy: efficient way to generate combinations from given rangesUsing numpy to build an array of all combinations of two arrays 但即便如此,我还是进入了 DiceNum > 10 的长时间运行。也许其他人有一个好主意,保留实用方法而不使用任何分析理论。

,

以下函数生成样本空间列表。下面的打印语句还显示了如何检索总和列表。在我的示例中,我没有将函数调用分配给要绘制的变量,但您可以自己实现。 (我不是万无一失的,所以如果这对您不起作用或您不理解,请告诉我)

def foo(n,rolls=[],roll=[]):
if n > 0:
    for i in range(1,7):
        foo(n-1,rolls,roll+[i])
else:
   rolls.append(roll)
return rolls

print(rolls:=foo(3),"\n\n",[sum(roll) for roll in rolls])

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。