K个N面骰子的不同点数组合数量

3
我需要计算从投掷K个N面骰子中可能出现的不同点数组合。我的定义是,例如{1,1,2,3,4}等同于{1,4,3,1,2}(顺序无关紧要),但与{1,1,3,3,3}不同(它们不是相同的结果集)。例如:Yahtzee是一款涉及投掷5个6面骰子的游戏——至少在重新投掷之前如此——因此不同的投掷次数为252。当N=K时,会导致OEIS序列A001700
如果我没有犯错,这可以通过"(N-1+K)选(N-1)"或等效地"(N+K-1)选K"来给出,即J语言中的K ! <: K + N。这让我想到了四种不同的隐式表示方法:
  • d =: ([ ! [: <: +)。简单的train,没有括号,尽管我需要使用大写字母。
  • d =: ([ (! <:) +)。没有大写字母,但内部hook需要加括号。
  • d =: (] !&<: +)。只有三个动词的train,但使用了一个Compose。它使用了(<: N) ! <: K + N版本。
  • d =: (([ ! +) * ] % +)。这个将"C(N+K-1,K)"重写为"C(N+K,K)*N/(N+K)"。它更丑陋,但在0个面数的0个骰子的情况下,它给出0而不是1,这可能是一个较少荒谬的答案。
哪一种方法最符合J语言的解决方案?
此外,所有这些的单调情况都没有意义:1 0 0 0 0 ...前三者和0 1 1 1 ...第四者。这个动词的更合理的单调形式应该是反身形式,如d~所示,因此把这个动词定义为(d~ : d)是否更好?
1个回答

2

我的偏好是:

d =: ([ (! <:) +)

并且要将单参选项添加到双参选项中

d =: d~ : ([ (! <:) +) NB. 4 d 5 ( 4 rolls of 5 sided dice : 70 possible combinations)

如果我以后遇到这个问题,我会在注释中添加示例参数和预期目的,以节省时间。

当然,如果0 d 0返回0,最终版本将是选择,即使它看起来有点复杂。


我理解您的喜好。如果期望投掷零个骰子或者零面的骰子,我会将 <code> [ (! <:) + </code> 修改为更宽的分支结构右侧: <code> & * ([ (! <:) +) </code>。 - kaleidic
我无法弄清楚如何使注释实际上显示代码。原始动词的左侧应该是星号和符号星号空格星号。(当然,空格是装饰性的,不是语义的。) - kaleidic
哦,你的意思是 (*&* * [ (! <:) +)?这是个好主意。你不能只对积进行符号函数处理,因为我认为用N面骰子掷0次有一种组合意义。但这个想法引导我们到了 (*@] * [ (! <:) +),它符合要求。不错! - algorithmshark
你在这里想出来的代码实际上是我的第一个想法,但我并不明白你所做的摇骰子和没有面之间的区别,因此我进行了泛化。 - kaleidic
如果 (*@] * [ (! <:) +) 符合要求,那么 (* *) @ ([ (! <:) +) 也应该符合。如果零面骰子只能朝一个方向投掷,那么 ( (* *) (! <:) + ) 也可以使用。 - bob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接