为掷骰子生成所有可能结果的矩阵(忽略顺序)

时间:2010-05-23 19:09:28

标签: algorithm r probability combinations dice

在订单确实重要的情况下,生成所有可能结果的矩阵相当容易。实现此目的的一种方法是使用expand.grid,如here所示。

如果没有怎么办?

如果我是对的,可能组合的数量是(S+N-1)!/S!(N-1)!,其中S是骰子的数量,每个骰子的编号为1到N.(它与众所周知的组合公式不同,因为它可以在多个骰子上出现相同的数字)。例如,当投掷四个六面骰子时,N = 6且S = 4,所以可能组合的数量是(4 + 6-1)!/ 4!(6-1)! = 9!/ 4!x5! = 126.如何生成这126种可能结果的矩阵?

谢谢。

2 个答案:

答案 0 :(得分:5)

以下是gd047和Marek提供的代码。

S <- 6 
N <- 4 
n <- choose(S+N-1,N) 
outcomes <- t(combn(S+N-1,N,sort)) - matrix(rep(c(0:(N-1)),each=n),nrow=n)

注意:这是最佳的,因为它不会尝试生成所有然后丢弃欺骗。 It actually generates only those that are required

解释其工作原理:

骰子上可能的数字是1到N.

假设您有一个骰子数的可能组合:x 1 ,x 2 ,...,x S 其中S是骰子的数量。

由于订单无关紧要,我们可以假设

x 1 ≤x 2 ≤...,≤x S

现在考虑序列x 1 ,x 2 + 1,x 3 + 2,...,x S + S-1。

(例如:1,1,1变为1,1 + 1,1 + 2 = 1,2,3)。

这个新序列的数字从1到N + S-1,所有数字都是不同的。

从你的骰子序列到我们创建的新序列的映射是1-1,很容易逆转。

因此,为了生成S骰子与数字1到N的可能组合,您需要做的就是生成所有N + S-1从1,2,...,N + S中选择S数的S组合-1。给定这样的组合,你可以对它进行排序,从最小的减去0,从第二个减去1,依此类推,得到你的骰子编号组合为1到N的S骰子。

例如,假设N = 6且S = 3.

您生成3个数字的组合,从1到6 + 3-1 = 8,即1,2,...,8中的3个数字。

说你得到3,6,7。这转换为3,6-1,7-2 = 3,5,5。

如果你有1,2,8。这将转化为1,1,6。

顺便说一句,这种映射也证明了你的公式。

答案 1 :(得分:1)

通常,您需要从原始expand.grid然后unique订购每个结果,例如使用apply:

X <- expand.grid(1:6,1:6,1:6,1:6)
dim(unique(t(apply(X,1,sort))))
#[1] 126   4

但是你可能会很棘手并选择所有订购结果的子集:

X <- expand.grid(1:6,1:6,1:6,1:6)
dim(subset(X, Var1>=Var2 & Var2>=Var3 & Var3>=Var4))
# [1] 126   4

第二版更快。