我正在尝试编写一个程序来显示掷 N 个骰子的示例 space
I'm trying to do a program that shows the sample space of throwing N dices
我正在尝试编写一个程序来显示 space 掷 N 个骰子的示例并写下每个骰子的结果,然后将每个骰子的结果相加对样本的每个元素进行骰子 space,最后用总和制作直方图。
我知道如何处理少量骰子,手动放置 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
循环?对这个算法有什么想法吗?
以下函数生成示例 space 列表。下面的打印语句还显示了如何检索总和列表。在我的示例中,我没有将函数调用分配给要绘制的变量,但您可以自己实现。 (我不是万无一失的,所以如果这对你不起作用或者你不明白,请告诉我)
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])
要像 Bill 提到的那样制作更直观的代码:
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],[2],[3],[4],[5],[6]] 开头:
所以我们转到函数的其他部分。现在我们遍历列表中的所有条目。从 d = [1] 开始。 (* 在列表前面给出所有元素 (*[a,b,c]=a,b,c)) 它获取每个掷出的骰子并将下一次掷出的结果相加。所以 [1] 变为 [[1,1],[1,2],[1,3],...,[1,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,2,...,6],然后以获得 diceNum 骰子的方式对其进行整形。
关于这里发生的事情的一个很好的解释(对我 xD 也有一点启发),你可以在这里找到 Numpy: efficient way to generate combinations from given ranges and Using numpy to build an array of all combinations of two arrays
但即使这样,我也会在 diceNum > 10 的情况下进入长时间运行。也许其他人有一个好主意,即保持实用方法而不使用任何分析理论。
我正在尝试编写一个程序来显示 space 掷 N 个骰子的示例并写下每个骰子的结果,然后将每个骰子的结果相加对样本的每个元素进行骰子 space,最后用总和制作直方图。
我知道如何处理少量骰子,手动放置 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
循环?对这个算法有什么想法吗?
以下函数生成示例 space 列表。下面的打印语句还显示了如何检索总和列表。在我的示例中,我没有将函数调用分配给要绘制的变量,但您可以自己实现。 (我不是万无一失的,所以如果这对你不起作用或者你不明白,请告诉我)
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])
要像 Bill 提到的那样制作更直观的代码:
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],[2],[3],[4],[5],[6]] 开头: 所以我们转到函数的其他部分。现在我们遍历列表中的所有条目。从 d = [1] 开始。 (* 在列表前面给出所有元素 (*[a,b,c]=a,b,c)) 它获取每个掷出的骰子并将下一次掷出的结果相加。所以 [1] 变为 [[1,1],[1,2],[1,3],...,[1,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,2,...,6],然后以获得 diceNum 骰子的方式对其进行整形。 关于这里发生的事情的一个很好的解释(对我 xD 也有一点启发),你可以在这里找到 Numpy: efficient way to generate combinations from given ranges and Using numpy to build an array of all combinations of two arrays 但即使这样,我也会在 diceNum > 10 的情况下进入长时间运行。也许其他人有一个好主意,即保持实用方法而不使用任何分析理论。