Algorithm 确定符号是否为第i个组合nCr的一部分

Algorithm 确定符号是否为第i个组合nCr的一部分,algorithm,function,combinations,combinatorics,Algorithm,Function,Combinations,Combinatorics,更新: 我最终需要的是组合数学和解列。 下面的链接很有帮助: 问题 给定N个符号的列表,如{0,1,2,3,4…} 以及这些的NCr组合 例如,NC3将产生: 0 1 2 0 1 3 0 1 4 ... ... 1 2 3 1 2 4 etc... 对于第i个组合(i=[1..NCr]),我想确定一个符号是否是它的一部分。 Func(N,r,i,s)=真/假或0/1 从上面继续 第一个组合包含0 1 2,但不包含3 F(N,3,1,"0") = TRUE

更新: 我最终需要的是组合数学和解列。 下面的链接很有帮助:

问题
给定N个符号的列表,如{0,1,2,3,4…}
以及这些的NCr组合

例如,NC3将产生:

0 1 2  
0 1 3  
0 1 4  
...  
...  
1 2 3  
1 2 4  
etc...  
对于第i个组合(i=[1..NCr]),我想确定一个符号是否是它的一部分。
Func(N,r,i,s)=真/假或0/1
从上面继续 第一个组合包含0 1 2,但不包含3

F(N,3,1,"0") = TRUE  
F(N,3,1,"1") = TRUE  
F(N,3,1,"2") = TRUE  
F(N,3,1,"3") = FALSE  
当前可能有用或相关的方法和技巧。
与矩阵的关系 对于r=2,例如4C2,组合是2D矩阵的上半部分(或下半部分)

    1,2 1,3 1,4  
    ----2,3 2,4  
    --------3,4  
对于r=3,它是3D矩阵或立方体的角 对于r=4,它是4D矩阵的“角”,依此类推

另一种关系
理想情况下,解决方案的形式类似于以下问题的答案:

长度为r的组合列表中的第n个组合(允许重复),可以计算第i个符号
使用整数除法和余数:

n/r^i%r=(0表示第0个符号,1表示第1个符号…等)

例如,对于3个符号中的第6个梳,第0个第一和第二个符号为:

i = 0 => 6 / 3^0 % 3 = 0   
i = 1 => 6 / 3^1 % 3 = 2   
i = 2 => 6 / 3^2 % 3 = 0   
第六个梳子将是0 2 0

我需要类似的东西,但不允许重复

感谢您关注这个问题:

凯文。

我相信你的问题在于或子集的问题

我将从软件包中用Mathematica为您提供一个实现,但是上面的Google链接可能是一个更好的起点,除非您熟悉语义

UnrankKSubset::usage = "UnrankKSubset[m, k, l] gives the mth k-subset of set l, listed in lexicographic order."

UnrankKSubset[m_Integer, 1, s_List] := {s[[m + 1]]}
UnrankKSubset[0, k_Integer, s_List] := Take[s, k]
UnrankKSubset[m_Integer, k_Integer, s_List] := 
       Block[{i = 1, n = Length[s], x1, u, $RecursionLimit = Infinity}, 
             u = Binomial[n, k]; 
             While[Binomial[i, k] < u - m, i++]; 
             x1 = n - (i - 1); 
             Prepend[UnrankKSubset[m - u + Binomial[i, k], k-1, Drop[s, x1]], s[[x1]]]
       ]
{0, 3, 4}
产生集合{0,1,2,3,4}的第6个(从0开始索引)长度-3组合。

这个问题有一个非常有效的算法,它也包含在最近出版的:
Knuth,《计算机编程艺术》,第4A卷(第7.2.1.3节)

因为您不关心组合的生成顺序,所以让我们使用组合的字典顺序,其中每个组合按降序列出。因此,对于r=3,3个符号的前11个组合将是:210、310、320、321、410、420、421、430、431、432、510。这种排序的优点是枚举独立于n;事实上,它是对{0,1,2,…}中3个符号的所有组合的枚举

有一种标准方法可以直接生成给定i的第i个组合,因此要测试符号
s
是否是第i个组合的一部分,只需生成它并进行检查即可

方法 有多少个r符号的组合以特定符号s开始?剩余的r-1位置必须来自s符号0,1,2,…,s-1,所以它是(s选择r-1),其中(s选择r-1)或C(s,r-1)是二项式系数,表示从s对象中选择r-1对象的方法的数量。因为这对所有s都是正确的,第i个组合的第一个符号是最小的s,因此

&总和;k=0s(k选择r-1)≥ 一,

一旦知道了第一个符号,问题就归结为找到第(i-&Sum;k=0s-1(k选择r-1))个r-1符号组合,其中我们减去了以小于s的符号开始的组合

代码 Python代码(您可以更高效地编写
C(n,r)
,但这对我们来说已经足够快了):

#/usr/bin/env python
tC={}
def C(n,r):
如果tC.具有_键((n,r)):返回tC[(n,r)]
如果r>n-r:r=n-r

如果r我已经编写了一个类来处理处理二项式系数的常用函数,这是您的问题所属的问题类型。它执行以下任务:

  • 将任意N选择K的所有K索引以良好格式输出到文件。可以用更具描述性的字符串或字母替换K索引。这种方法使得解决这类问题变得非常简单

  • 将K索引转换为已排序二项系数表中某个条目的正确索引。这种技术比以前发布的依赖于迭代的技术要快得多。它通过使用帕斯卡三角形固有的数学特性来实现这一点。我的论文谈到了这一点。我相信我是第一个发现并发表这项技术的人,但我可能错了

  • 将已排序的二项式系数表中的索引转换为相应的K索引

  • 使用此方法计算二项式系数,它不太可能溢出,并且适用于较大的数字

  • 该类是用.NETC#编写的,它提供了一种通过使用泛型列表来管理与问题相关的对象(如果有)的方法。这个类的构造函数接受一个名为InitTable的bool值,如果为true,它将创建一个通用列表来保存要管理的对象。如果此值为false,则不会创建表。执行上述4种方法不需要创建表。提供了访问器方法来访问表

  • 有一个关联的测试类,它显示了如何使用该类及其方法。它已经过2个案例的广泛测试,没有已知的bug

  • 要阅读有关此类的信息并下载代码,请参阅


    这门课可以很容易地应用于你的问题。如果您拥有二项式系数表的秩(或索引),那么只需调用在数组中返回K索引的类方法。然后,遍历返回的数组,查看是否有任何K索引值与您拥有的值匹配。非常简单…

    也许可以添加
    作业
    tag@Amit为什么你认为这是家庭作业?问题交叉张贴在。(所以我在这里交叉发布了我的答案。:p有更多的代码,没有TeX标记。)更新:组合和取消分级最终是我需要的。下面的链接帮助很大:谢谢你的接受。我很高兴这有帮助。
    UnrankKSubset[5, 3, {0, 1, 2, 3, 4}]
    
    {0, 3, 4}