有没有一种方法可以得到;组合组“;没有';在Python上使用itertools是否会重叠,并且是详尽的?

有没有一种方法可以得到;组合组“;没有';在Python上使用itertools是否会重叠,并且是详尽的?,python,algorithm,math,discrete-mathematics,Python,Algorithm,Math,Discrete Mathematics,我的意思是:如果你找到[1,2,3,4]的所有可能的2元素组合,你会得到[1,2],[1,3],[1,4],[2,3],[2,4]和[3,4] 我想要的是一组不重叠且包含所有元素的组合。因此,例如[[1,2],[3,4]]是一个“组”的示例,因为两个组合中的元素不重叠,并且使用了所有可能的元素。[[1,3],[2,4]]是另一个“群体”的例子 顺便说一下,我知道itertools允许我自己打印组合。例如,下面的代码: combinations = itertools.combinations([

我的意思是:如果你找到[1,2,3,4]的所有可能的2元素组合,你会得到[1,2],[1,3],[1,4],[2,3],[2,4]和[3,4]

我想要的是一组不重叠且包含所有元素的组合。因此,例如[[1,2],[3,4]]是一个“组”的示例,因为两个组合中的元素不重叠,并且使用了所有可能的元素。[[1,3],[2,4]]是另一个“群体”的例子

顺便说一下,我知道itertools允许我自己打印组合。例如,下面的代码:

combinations = itertools.combinations([1,2,3,4], 2)
for c in combinations:
    print(c)
将输出:

(1, 2)
(1, 3)
(1, 4)
(2, 3)
(2, 4)
(3, 4)
但同样,这只是给了我一些组合。我想要一组与元素相互排斥且详尽的组合

另外,我肯定我没有使用正确的词汇。如果我所描述的任何东西都有一个正式的术语,我会很感激学习它


提前谢谢

这些“组合组”可以称为
将分区设置为大小为k的部分

我假设
k
n
的除数,所以有
p=n/k
部分

现在我们可以递归地将项目分布到各个部分。为了避免重复生成相同的分区(如
01 23 45
01 45 23
),我们应该限制每个组中领先(最小)元素的位置

这里我使用了
lastfilled
参数作为最右边填充部分的索引,因此项目0始终属于第0部分,项目1可能属于第0部分或第1部分,但不属于第2部分,依此类推。具有中间结果的
01\uuuuuuuuuuu
我们只能在下一级生成
01 2\uuuuuuu
,而不能生成
01\uuuuuuu

注意,这样的分区的数量是

NPK(n,k) = n! / ((k!)^p * p!)
而且增长很快(
280
对于
n=9,k=3
1401400
对于
15/3
)。(发现)

Python代码。为了节省内存,我使用了零件内容的全局列表和它们中已占用位置的计数,所以在递归调用之后,我必须将计数重置为以前的状态

n = 6
k = 2
p = n // k
parts = [[0]*k for _ in range(p)]
cnts = [0]*p

def genparts(m, lastfilled):
    if m == n:
        print(parts)
        return
    for i in range(min(p, lastfilled + 2)):
        if cnts[i] < k:
            parts[i][cnts[i]] = m
            cnts[i] += 1
            genparts(m+1, max(i, lastfilled))
            cnts[i] -= 1

genparts(0, -1)

[[0, 1], [2, 3], [4, 5]]
[[0, 1], [2, 4], [3, 5]]
[[0, 1], [2, 5], [3, 4]]
[[0, 2], [1, 3], [4, 5]]
[[0, 2], [1, 4], [3, 5]]
[[0, 2], [1, 5], [3, 4]]
[[0, 3], [1, 2], [4, 5]]
[[0, 4], [1, 2], [3, 5]]
[[0, 5], [1, 2], [3, 4]]
[[0, 3], [1, 4], [2, 5]]
[[0, 3], [1, 5], [2, 4]]
[[0, 4], [1, 3], [2, 5]]
[[0, 5], [1, 3], [2, 4]]
[[0, 4], [1, 5], [2, 3]]
[[0, 5], [1, 4], [2, 3]]
n=6
k=2
p=n//k
部分=[[0]*k表示范围内(p)]
cnts=[0]*p
def GENPORTS(m,最后填充):
如果m==n:
印刷品(部分)
返回
对于范围内的i(最小(p,最后填充+2)):
如果cnts[i]
它看起来像。如果是这样的话,这也是一个。注意,你不可能每次都有一个解决方案。例如:当您的初始集合包含奇数个元素时,如果您要求大小为2的组,则不可能覆盖所有集合而不重叠。对不起,我这一周很忙。这个答案很完美,谢谢!嘿,你能解释下一行的目的吗:l=[i代表范围内的i(n)]这是第一次试用中的一个工件,移除了。好的。实际上,我正在努力修改您的代码,使其返回列表列表给我,而不仅仅是打印出组合。我在genparts函数中添加了一个名为myList的附加参数。然后我将print(parts)改为myList.append(parts)。当我调用列表上的函数时,列表只包含最后一个分区。知道我做错了什么吗?导入副本并制作
lst.append(copy.deepcopy(parts))
以避免添加同一对象的副本(指向
parts