我如何生成排列列表的列表

时间:2018-10-13 07:29:45

标签: python python-3.x algorithm data-structures

假设我有一个模式[2, 1]的列表,并给了一个length = 5

此模式表示在length = 5列表中,该列表中依次包含2个和1个“ 1”。

连续组之间的间隔或0也必须至少一个。

我尝试过的是:

for curr_col in pattern_list:

    curr_pattern = curr_col

    example_combo = [0] * dim0
    idx, group_strt_idxs = 0, []
    for num in curr_pattern :
        group_strt_idxs.append(idx)
        for i in range(num ):
            example_combo[idx] = 1
            idx += 1
        if idx < dim0 and dim0 > 1:
            example_combo[idx] = 0
            idx += 1
    print('ex', example_combo)

请帮助!

2 个答案:

答案 0 :(得分:1)

问题是将零放入len(constraints_list) + 1存储桶中。第一个和最后一个可以包含0个或多个零,中间的一个必须包含至少一个。

我们在repartitions函数中生成可能的分区。这样就很容易构建相应的列表:

from itertools import zip_longest 


def repartitions(number, buckets, start=None):
    if start is None:
        start = []
        mini = 0 # first sequence of zeros can be empty
    else:
        mini = 1 # others contain at least one zero

    if buckets == 1:
        # last bucket, we put all remaining zeros here
        start = start + [number]
        yield start
    else:
        for i in range(mini, number-buckets+3):
            # we have to keep at least 1 zero for each other bucket
            # except the last one.
            current = start + [i]
            yield from repartitions(number-i, buckets-1, current)


def permutations_with_constraints(constraints_list, length):
    number_of_zeros = length - sum(constraints_list)
    buckets = len(constraints_list) + 1
    for rep in repartitions(number_of_zeros, buckets):
        out = sum(([0]*zeros + [1]*ones 
                   for zeros, ones in zip_longest(rep, constraints_list, fillvalue=0)), [])
        yield out    

一些例子:

print(list(permutations_with_constraints([1, 2], 5)))
# [[1, 0, 1, 1, 0], [1, 0, 0, 1, 1], [0, 1, 0, 1, 1]]

print(list(permutations_with_constraints([2, 3, 2], 11)))
# [[1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0], 
# [1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0],
# [1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1],
# [1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0],
# [1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1],
# [1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1],
# [0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0],
# [0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1],
# [0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1],
# [0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1]]

关于总和的一些解释,如您在评论中所要求的:

我们有一个rep列表,和一个简短的constraints列表。我们用zipzip_longest fillvalue=0 [(rep[0], constraints[0]), (rep[1], constraints[1]), ... (rep[-1], 0)]0。 (它实际上是一个生成器,而不是列表,但这对解释没有任何改变)。最后一个(2, 3)填充约束中的缺失值。

然后,我们从每个元组构建一个列表。例如,[0, 0, 1, 1, 1]将给我们sum[]然后使用pip install -r requirements.txt作为起始值添加这些列表。

答案 1 :(得分:0)

由于已经给出了1组的长度,因此递归可以确定每个组的位置:

def generate_groups(d, fill=1):
  return [[fill]*i for i in d]

def all_groups(_d, _len):
  def groupings(d, current = []):
    if sum(not i for i in current) == d and sum(i == '*' for i in current) == len(_d):
      yield current
    else:
      if sum(not i for i in current) < d:
         yield from groupings(d, current+[0])
      if not current or not current[-1]:
         yield from groupings(d, current+['*'])
  return [(lambda x, y:[c for h in y for c in ([h] if not h else next(x))])(iter(generate_groups(_d)), i) 
    for i in groupings(_len-sum(_d))]

print(all_groups([2, 1], 5))
print(all_groups([2, 3, 2], 11))

输出:

[[0, 1, 1, 0, 1], [1, 1, 0, 0, 1], [1, 1, 0, 1, 0]]
[[0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1], [0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1], [0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1], [0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0], [1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1], [1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1], [1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0], [1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0], [1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0]]