R语言循环调用自定义函数填充骰子组合数矩阵问题求解
R语言循环填充骰子组合数矩阵实现
原代码核心问题
- 自定义函数逻辑错误:第二个循环计算的
r变量完全未被使用,c <- cumsum(l)属于无效计算,额外定义的H、l参数和2-6点五面骰子的组合数计算逻辑无关,属于冗余错误代码 - 变量未初始化:函数内的
a、r向量未提前声明,循环赋值容易触发环境变量继承错误 - 矩阵未预初始化:循环直接对
M[j,i]赋值,没有提前指定矩阵维度,会触发下标越界或自动补全错误 - 循环边界错误:总点数循环从1开始,实际上t个2-6点骰子的最小总点数是
2*t,小于该值的结果恒为0,不需要重复计算 - 流程控制错误:
return(M)写在外层循环内部,第一次迭代就会终止运行,无法完成全量填充;代码末尾多写了一个右大括号,会触发语法错误 - 函数传参错误:自定义函数定义了5个入参,原循环调用时只传入了3个,缺少参数会直接运行报错
修正后可运行代码
首先修正组合数计算函数,去掉冗余逻辑,用R内置choose()函数计算组合数,自动处理边界无效情况:
# 组合数计算函数:返回t个2-6点五面骰子,掷出总点数为target的组合数 combination <- function(t, target) { # 总点数不在合法范围直接返回0 if (target < 2*t | target > 6*t) { return(0) } # 容斥原理计算:将2-6点骰子平移为1-5点,总点数等价替换为target - t n <- target - t k <- t max_i <- floor((n - k)/5) # 容斥最大迭代次数 res <- 0 for (i in 0:max_i) { res <- res + ((-1)^i) * choose(t, i) * choose(n - 5*i - 1, k - 1) } return(res) }
初始化矩阵后循环填充,覆盖最多20个骰子的所有可能取值:
max_dice <- 20 # 设定最大骰子数量 max_point <- 6 * max_dice # 最大可能总点数为20*6=120 # 初始化矩阵:行对应总点数(1~120,1点不存在留空即可),列对应骰子数量(1~20),初始值全为0 M <- matrix(0, nrow = max_point, ncol = max_dice) # 双层循环填充矩阵 for (i in 1:max_dice) { # i为当前骰子数量 min_p <- 2*i # i个骰子的最小可掷出总点数 max_p <- 6*i # i个骰子的最大可掷出总点数 for (j in min_p:max_p) { # j为当前计算的总点数 M[j, i] <- combination(t = i, target = j) } }
结果查询方法
矩阵行索引对应总点数,列索引对应骰子数量,例如要查询总点数为10时不同骰子数的组合数,直接取第10行的非零值即可:
> M[10, 1:5] # 输出1-5个骰子掷出10点的组合数 [1] 0 3 15 14 3
和需求给出的示例完全匹配:2个骰子对应3种组合、3个骰子对应15种组合,结果正确。如果要查固定骰子数固定点数的组合数,直接取对应位置即可,比如M[10,2]就是2个骰子掷出10点的组合数,返回值为3。
内容的提问来源于stack exchange,提问作者Yellow Dot
相关产品推荐
相关产品推荐

