与此问题相关,我想知道算法(如果有的话,还有Java / c / c ++ / python / etc中的实际代码!)r为列表生成的所有元素组合在一起的元素m总数。其中一些m元素可能会重复。
r
m
谢谢!
我认为这是与 Mathematica中的 Jean-Bernard Pellerin算法紧密相关的递归。
这将输入作为每种类型元素的编号。输出格式类似。例如:
{a,a,b,b,c,d,d,d,d} -> {2,2,1,4}
功能:
f[k_, {}, c__] := If[+c == k, {{c}}, {}] f[k_, {x_, r___}, c___] := Join @@ (f[k, {r}, c, #] & /@ 0~Range~Min[x, k - +c])
用:
f[4, {2, 2, 1, 4}] {{0,0,0,4},{0,0,1,3},{0,1,0,3},{0,1,1,2},{0,2,0,2} , {0,2,1,1},{1,0,0,3},{1,0,1,2},{1,1,0,2},{1,1,1,1}, {1,2,0,1},{1,2,1,0},{2,0,0,2},{2,0,1,1},{2,1,0,1}, {2,1,1,0},{2,2,0,0}}
要求对此代码进行解释。它是一个递归函数,需要可变数量的参数。第一个参数是k,子集的长度。第二个是要选择的每种类型的计数列表。函数在内部使用第三个参数及其他参数来保存子集(组合),使其得以构造。
k
因此,当选择集中没有更多项目时,将使用此定义:
f[k_, {}, c__] := If[+c == k, {{c}}, {}]
如果组合值的总和(其长度)等于k,则返回该组合,否则返回一个空集。(+c是的简写Plus[c])
+c
Plus[c]
除此以外:
f[k_, {x_, r___}, c___] := Join @@ (f[k, {r}, c, #] & /@ 0~Range~Min[x, k - +c])
从左到右阅读:
Join 用于平整嵌套列表的级别,以使结果不会变得越来越深。
Join
f[k, {r}, c, #] &调用函数,删除选择集的第一个位置(x),并向组合(#)添加新元素。
f[k, {r}, c, #] &
x
#
/@ 0 ~Range~ Min[x, k - +c])对于介于0和选择集第一个元素中较小者之间的每个整数,以及k组合总数较少,这是在不超过组合大小的情况下可以选择的最大值k。
/@ 0 ~Range~ Min[x, k - +c])