生成一个包含所有可能掷骰子结果的矩阵(忽略顺序)
Posted
技术标签:
【中文标题】生成一个包含所有可能掷骰子结果的矩阵(忽略顺序)【英文标题】:Generate a matrix of all possible outcomes for throwing n dice (ignoring order) 【发布时间】:2011-02-22 23:55:22 【问题描述】:在顺序确实很重要的情况下,生成所有可能结果的矩阵相当容易。一种方法是使用expand.grid
,如here 所示。
如果没有怎么办?
如果我是对的,可能的组合数是(S+N-1)!/S!(N-1)!
,其中 S 是骰子的数量,每个骰子的 N 面编号为 1 到 N。(它与众所周知的组合公式不同,因为它是可能的相同的数字出现在多个骰子上)。例如,当掷四个六面骰子时,N=6,S=4,所以可能的组合数是(4+6-1)!/4!(6-1)! = 9!/4!x5! = 126. 如何生成这 126 种可能结果的矩阵?
谢谢。
【问题讨论】:
重新标记以添加骰子和算法。 【参考方案1】:这是 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。
假设给定骰子编号的可能组合: x1 , x2 , ..., xS 其中 S是骰子的数量。
由于顺序无关紧要,我们可以假设
x1 ≤ x2 ≤ ..., ≤ xS.
现在考虑序列 x1, x2 + 1, x3 + 2, ..., xS + 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,依此类推,得到 S 骰子的骰子编号组合,编号为 1 到 N。
例如,假设 N = 6 和 S = 3。
您生成 1 到 6+3-1 = 8 的 3 个数字的组合,即 1,2,...,8 的 3 个数字。
假设你得到 3,6,7。这转换为 3, 6-1, 7-2 = 3,5,5。
如果你有 1,2,8。这将转换为 1,1,6。
顺便说一句,这个映射也证明了你的公式。
【讨论】:
@Moron 你是对的!我在阅读您的答案之前发布,注意到其中没有代码。毫无疑问,您首先回答了,所以我将我的代码添加为您的答案的评论。 S @gd047。好的,我已经编辑了答案以添加您的代码。如果您觉得需要任何内容,请随时编辑答案。 这是一个非常全面的答案。代码提示:combn
可以对每个组合应用一个函数,因此apply(combn(S+N-1,N),2,sort)
可以替换为combn(S+N-1,N,sort)
。【参考方案2】:
一般来说,您需要从原始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
第二个版本更快。
【讨论】:
以上是关于生成一个包含所有可能掷骰子结果的矩阵(忽略顺序)的主要内容,如果未能解决你的问题,请参考以下文章
python 由用户输入掷多少次骰子,然后统计每个面出现的次数
LeetCode 1223. 掷骰子模拟 Dice Roll Simulation - Java - DP
从 5 次掷骰子中,生成一个范围为 [1 - 100] 的随机数
Leetcode练习(Python):数组类:第54题:给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。