生成第k个组合而不生成/迭代先前

时间:2013-08-30 01:44:30

标签: python combinations itertools

给定一组项目,例如:

[ 1, 2, 3, 4, 5, 6 ]

我希望通过重复生成一定长度的所有可能组合。扭曲是我想以预定的组合开始(一种偏移到组合列表中)。

例如,从这开始:

[ 1, 5, 6 ]

第一个(下一个)组合将是:

[ 1, 6, 6 ]

我已经成功使用itertools.combinations_with_replacement()来生成组合,但是这个项目需要使用一个生成太多组合的集合 - 首先创建它们并迭代到正确的点不是可能的。

我发现this example for generating kth combination似乎对我来说效果不佳。 This answer似乎是另一种可能性,但我似乎无法将它从C移植到Python。

到目前为止,这是使用kth combination example

的代码
import operator as op
items = [ 1,2,3,4,5,6 ]

# https://stackoverflow.com/a/4941932/1167783
def nCr(n, r):
    r = min(r, n-r)
    if r == 0: 
        return 1
    numer = reduce(op.mul, xrange(n, n-r, -1))
    denom = reduce(op.mul, xrange(1, r+1))
    return numer // denom

# https://stackoverflow.com/a/1776884/1167783
def kthCombination(k, l, r):
    if r == 0:
        return []
    elif len(l) == r:
        return l
    else:
        i = nCr(len(l)-1, r-1)
        if k < i:
            return l[0:1] + kthCombination(k, l[1:], r-1)
        else:
            return kthCombination(k-i, l[1:], r)

# get 1st combination of 3 values from list 'items' 
print kthCombination(1, items, 3)

# returns [ 1, 2, 4 ]

任何帮助都会很棒!

2 个答案:

答案 0 :(得分:3)

如果假设数组中的所有值都是base-n编号系统中的数字,其中n是数组的长度,则第k个组合将等于以base-n表示的k。

如果您想要从给定组合开始(即[1,6,5])并从那里继续,只需将此起点读作base-n中的数字。然后,您可以通过递增来开始迭代连续组合。

编辑:进一步解释:

让我们从数组开始吧。该数组包含6个值,因此我们在base-6中工作。我们假设数组中每个元素的索引是元素的base-6值。

base-6中的值范围从0到5.这可能会让人感到困惑,因为我们的示例使用数字,但我们可以使用任何组合来完成此操作。我会在我们合并的数字周围加上“引号”标记。

给定组合['1','6','5'],我们首先需要将其转换为base-6值。 '1'变为0,'6'变为5,'5'变为4.使用它们在起始值中的位置作为它们在base-6中的幂,我们得到:

(0 * 6 ^ 0)+(5 * 6 ^ 1)+(4 * 6 ^ 2)= 174(十进制)

如果我们想知道下一个组合,我们可以添加1.如果我们想要提前知道20个组合,我们添加20.我们也可以减去倒退。让我们添加1到174并将其转换回base-6:

175(十进制)=(1 + 6 ^ 0)+(5 * 6 ^ 1)+(4 * 6 ^ 2)= 451(base-6)= ['2','6','5 '](组合)

有关数字基础的更多信息,请参阅http://en.wikipedia.org/wiki/Radixhttp://en.wikipedia.org/wiki/Base_%28exponentiation%29

答案 1 :(得分:2)

您可以映射数字,而不是发明轮次时间数37,289,423,987,239,489,826,364,653(仅计算人类)。 itertools将返回第一个组合[1,1,1],但您需要[1,5,6]。只需将[0,4,5] mod 6添加到每个位置即可。当然,您也可以在数字,对象和模数之间来回映射。

即使每个位置的元素数量不同,这也有效。

不过,你会对你的开始有更多的乐趣。