产生子组合

时间:2011-12-27 15:15:58

标签: python algorithm python-3.x

我需要一个函数来返回给定段的子段。例如,sub_combinations("ABCD")应该产生:

("A", "B", "C", "D")
("A", "B", "CD")
("A", "BC", "D")
("A", "BCD")
("AB", "C", "D")
("AB", "CD")
("ABC", "D")
("ABCD")
("ABD", "C") *
("AC", "BD") *
("AC", "B", "D") *
("ACD", "B") *
("AD", "BC") *
("AD", "B", "C") *

("A","C","B","D")无效,因为它不按顺序排列。换句话说,("A","B","C","D")是正确的。

("AC", "B", "D")有效,因为“C”按顺序跟随“A”,“B”跟随“AC”。

就我而言:

def sub_combinations(segment):
        for i in range(1, len(segment)):
                for j in sub_combinations(segment[i:]):
                        yield (segment[:i],) + j 
        yield (segment,) 

for i in sub_combinations("ABCD"):
        print(i)

('A', 'B', 'C', 'D')
('A', 'B', 'CD')
('A', 'BC', 'D')
('A', 'BCD')
('AB', 'C', 'D')
('AB', 'CD')
('ABC', 'D')
('ABCD',)

然而,缺少这些额外的组合。

有关如何进行的任何建议?

4 个答案:

答案 0 :(得分:5)

您可以按如下方式更改代码:

def sub_combinations(segment):
  if len(segment) == 1:
    yield (segment,)
  else:
    for j in sub_combinations(segment[1:]):
      yield (segment[0],)+j
      for k in range(len(j)):
        yield (segment[0]+j[k],)+j[:k]+j[k+1:]

如果您的细分只包含一个字符,则结果非常简单。否则拆分第一个字符并确定其余字符串的所有分区。之后你有以下(不同的)解决方案:splitt-off字符构建一个单独的元组,或者你可以将它添加到你以前的解决方案的任何元组。

由于递归调用,此方法构建从单个字符大小写到完整参数的解决方案集。

您的示例案例给出了以下结果:

('A', 'B', 'C', 'D')
('AB', 'C', 'D')
('AC', 'B', 'D')
('AD', 'B', 'C')
('A', 'BC', 'D')
('ABC', 'D')
('AD', 'BC')
('A', 'BD', 'C')
('ABD', 'C')
('AC', 'BD')
('A', 'B', 'CD')
('AB', 'CD')
('ACD', 'B')
('A', 'BCD')
('ABCD',)

答案 1 :(得分:1)

好吧,使用itertools library,我想出了这个:

from itertools import permutations
def sub_combinations(iterable, r):
    pool = tuple(iterable)
    n = len(pool)
    for indices in permutations(range(n), r):
        if sorted(indices) == list(indices):
            yield tuple(pool[i] for i in indices)

def combinations(s):
    l = len(s)
    for i in range(1, l+1):
        for item in sub_combinations(s, i):
             yield item

答案 2 :(得分:1)

你应该取第一个元素(“A”)+剩下的所有分区,所以得到:
“A”,“AB”,“AC”,“AD”,“ABC”,“ABD”,“ACD”,“ABCD”,然后对于每个集合,您必须考虑剩下的并应用相同的例程(选择第一个元素并扩展剩余的所有分区,等等......

通过这种方式处理,您将获得所需的列表而无需重复。

答案 3 :(得分:1)

  1. 生成集合{'A', 'B', 'C', 'D'}
  2. 的所有分区
  3. 对于每个分区,连接内部集合,并对外部集合进行排序。
  4. 搜索set partition给出this,因此只需稍加修改并转换Python 3的代码即可获得

    def sub_combinations(set_):
        if not set_:
            yield []
            return
        for i in range(1<<(len(set_)-1)):
            parts = [[], []]
            for item in set_:
                parts[i&1].append(item)
                i >>= 1
            for b in sub_combinations(parts[1]):
                yield sorted(''.join(x) for x in [parts[0]]+b)
    
    for p in sub_combinations("abcd"):
        print(p)
    

    打印

    ['abcd']
    ['a', 'bcd']
    ['acd', 'b']
    ['ab', 'cd']
    ['a', 'b', 'cd']
    ['abd', 'c']
    ['ac', 'bd']
    ['a', 'bd', 'c']
    ['ad', 'bc']
    ['ad', 'b', 'c']
    ['abc', 'd']
    ['a', 'bc', 'd']
    ['ac', 'b', 'd']
    ['ab', 'c', 'd']
    ['a', 'b', 'c', 'd']