【问题标题】:Generate all permutations where length of a permutation > # of elements in Python生成所有排列,其中排列的长度> Python中的元素数
【发布时间】:2018-07-13 18:04:56
【问题描述】:

我想从这些元素生成排列(元组):

[None, 0, 1, 2]. 

我希望每个排列的长度为 5 并且始终包含 3 个无。一个这样的排列的例子:

(None, 0, None, None, 1).

我目前在 Python 3.x 中创建了这个算法:

[state for state in list(set(it.permutations((None, None, None, 0, 0, 1, 1, 2, 2), 5))) if state.count(None)==3]

但是,我觉得这个算法不是最理想的(而且,嗯,丑陋),我不完全确定它是否正确。有没有更好的解决方案?我仔细阅读了 NumPy,但没有发现任何对我有帮助的东西。

感谢您的帮助!

【问题讨论】:

  • 查看sympy.utilities.iterables import multiset_permutations。本质上,您想要多重集 {None, None, None, 0, 1, 2} 的所有排列

标签: python algorithm permutation


【解决方案1】:

你可以创建一个递归函数:

def group(d, current = [], in_place = [None, 3]):
  need, _occurs = in_place
  if len(current) == 5 and current.count(need) == _occurs:
    yield current
  else:
    for i in d:
      _c = current+[i]
      if len(_c) <= 5 and _c.count(need) <= _occurs:
        yield from group(d, current = _c)

输出:

[[None, None, None, 0, 0], [None, None, None, 0, 1], [None, None, None, 0, 2], [None, None, None, 1, 0], [None, None, None, 1, 1], [None, None, None, 1, 2], [None, None, None, 2, 0], [None, None, None, 2, 1], [None, None, None, 2, 2], [None, None, 0, None, 0], [None, None, 0, None, 1], [None, None, 0, None, 2], [None, None, 0, 0, None], [None, None, 0, 1, None], [None, None, 0, 2, None], [None, None, 1, None, 0], [None, None, 1, None, 1], [None, None, 1, None, 2], [None, None, 1, 0, None], [None, None, 1, 1, None], [None, None, 1, 2, None], [None, None, 2, None, 0], [None, None, 2, None, 1], [None, None, 2, None, 2], [None, None, 2, 0, None], [None, None, 2, 1, None], [None, None, 2, 2, None], [None, 0, None, None, 0], [None, 0, None, None, 1], [None, 0, None, None, 2], [None, 0, None, 0, None], [None, 0, None, 1, None], [None, 0, None, 2, None], [None, 0, 0, None, None], [None, 0, 1, None, None], [None, 0, 2, None, None], [None, 1, None, None, 0], [None, 1, None, None, 1], [None, 1, None, None, 2], [None, 1, None, 0, None], [None, 1, None, 1, None], [None, 1, None, 2, None], [None, 1, 0, None, None], [None, 1, 1, None, None], [None, 1, 2, None, None], [None, 2, None, None, 0], [None, 2, None, None, 1], [None, 2, None, None, 2], [None, 2, None, 0, None], [None, 2, None, 1, None], [None, 2, None, 2, None], [None, 2, 0, None, None], [None, 2, 1, None, None], [None, 2, 2, None, None], [0, None, None, None, 0], [0, None, None, None, 1], [0, None, None, None, 2], [0, None, None, 0, None], [0, None, None, 1, None], [0, None, None, 2, None], [0, None, 0, None, None], [0, None, 1, None, None], [0, None, 2, None, None], [0, 0, None, None, None], [0, 1, None, None, None], [0, 2, None, None, None], [1, None, None, None, 0], [1, None, None, None, 1], [1, None, None, None, 2], [1, None, None, 0, None], [1, None, None, 1, None], [1, None, None, 2, None], [1, None, 0, None, None], [1, None, 1, None, None], [1, None, 2, None, None], [1, 0, None, None, None], [1, 1, None, None, None], [1, 2, None, None, None], [2, None, None, None, 0], [2, None, None, None, 1], [2, None, None, None, 2], [2, None, None, 0, None], [2, None, None, 1, None], [2, None, None, 2, None], [2, None, 0, None, None], [2, None, 1, None, None], [2, None, 2, None, None], [2, 0, None, None, None], [2, 1, None, None, None], [2, 2, None, None, None]]

【讨论】:

  • 排列不是没有重复吗?是例如[None, None, None, 0, 0] 有效(我指的是本例中的数字)?
  • @AndrejKesely 在数学中,排列必须包括所有元素。所以作者想要的已经不是真正的排列了。那么问题是他真正想要的是什么......
  • @AndrejKesely:[None, None, None, 0, 0] 是有效的。真的不知道排列没有重复(这可能就是为什么我必须将三个无和两个 0、1 和 2 放入元素列表中以从中进行“排列”)。
  • @tien 好的,我很困惑,那我得改一下答案了。
【解决方案2】:

如果我真的不想生成和过滤掉一堆不合适的条目,我会采取以下方法:

您需要 0 到 3 个 Nones(拨打该号码 n1),然后是列表中的一个非 None 项目,然后是 0 到 3-n1Nones (@987654326 @),然后是列表中的第二个非None 项目,然后是 3-n1-n2Nones。

states = []
for (i1, i2) in permutations((0,1,2), 2):
    for n1 in range(4):
        for n2 in range(4-n1):
            states.append((None,)*n1 + (i1,) + (None,)*n2 + (i2,) + (None,)*(3-n1-n2))

【讨论】:

    【解决方案3】:

    假设(根据您的代码输出以及您故意添加 0、1 和 2 的多个副本的事实)您正在执行“置换置换”,或者基本上是具有 3 个无要求的笛卡尔积,我会做类似的事情:

    def tien_gen(size, values, number_of_nones):
        to_fill = size - number_of_nones
        for locs in itertools.combinations(range(size), to_fill):
            for fill_values in itertools.product(values, repeat=to_fill):
                out = [None] * size
                for loc, fill_value in zip(locs, fill_values):
                    out[loc] = fill_value
                yield tuple(out)
    

    与您的输出匹配:

    In [137]: result = list(tien_gen(5, [0,1,2], 3))
    
    In [138]: len(result)
    Out[138]: 90
    
    In [139]: result
    Out[139]: 
    [(0, 0, None, None, None),
     (0, 1, None, None, None),
     (0, 2, None, None, None),
     (1, 0, None, None, None),
     [...]
     (None, 0, None, 1, None),
     (None, 0, None, 2, None),
     (None, 1, None, 0, None),
     [...]
     (None, 2, None, 1, None),
     (None, 2, None, 2, None),
     (None, 0, None, None, 0),
     (None, 0, None, None, 1),
     [...]
     (None, None, None, 1, 2),
     (None, None, None, 2, 0),
     (None, None, None, 2, 1),
     (None, None, None, 2, 2)]
    
    In [140]: orig = [state for state in list(set(it.permutations((None, None, None, 0, 0, 1, 1, 2, 2), 5))) if state.count(None)==3]
    
    In [141]: len(result) == len(orig) and set(result) == set(orig)
    Out[141]: True
    

    对于小尺寸,优势是有限的,但对于较大尺寸,这样可以避免生成任何不使用的元组,而且由于它是一个生成器,如果你不使用它们就不必全部实现想要。

    【讨论】:

      【解决方案4】:

      从概念上讲,我认为最简单的“高效”算法可以解释为:首先生成长度为 2 的排列。然后,以所有可能的方式插入 None 的 3 个实例。

      但是,改为更有效:首先,在您希望两个元素所在的位置生成所有索引。然后,对于每个长度为 2 的排列的每组索引,将这些元素替换为给定的索引。

      from itertools import combinations, permutations, product
      
      base_list = [None] * 5
      values = [0, 1, 2]
      
      all_indices = combinations(range(5), 2)
      all_perms = permutations(values, 2)
      
      for (i, j), (x, y) in product(all_indices, all_perms):
          list_copy = base_list[:]
          list_copy[i] = x
          list_copy[j] = y
          print(list_copy)
      
      # [0, 1, None, None, None]
      # [0, 2, None, None, None]
      # ...
      # [None, None, None, 2, 0]
      # [None, None, None, 2, 1]
      

      这应该可以很容易地扩展为不同长度的输入。

      def inserted_permutations(size, values, insert_count, default=None):
          base = [default] * size
          all_indices = combinations(range(size), insert_count)
          all_perms = permutations(values, insert_count)
          for indices, values in product(all_indices, all_perms):
              base_copy = base[:]
              for index, value in zip(indices, values):
                  base_copy[index] = value
              yield base_copy
      

      【讨论】:

        【解决方案5】:
        from itertools import product
        
        elemets = [None, 0, 1, 2]
        l = product(elemets, repeat=5)
        s = set(p for p in l if p.count(None) == 3)
        
        print(s)
        

        输出:

        {(None, None, None, 0, 2), (None, None, 0, None, 2), (1, 2, None, None, None), (0, None, None, 1, None), (1, None, 2, None, None), (1, None, None, 2, None), (None, 2, 1, None, None), (None, None, None, 2, 1), (None, None, 2, None, 1), (None, None, None, 1, 1), (None, 0, None, 0, None), (None, 0, 0, None, None), (None, 1, None, None, 1), (2, 1, None, None, None), (2, None, None, 1, None), (None, 0, None, None, 1), (None, 0, None, 1, None), (0, None, None, 0, None), (0, None, 0, None, None), (None, None, 1, 1, None), (1, None, None, 1, None), (2, None, None, 2, None), (2, None, 2, None, None), (None, None, 2, None, 0), (None, None, None, 2, 0), (None, None, None, 1, 2), (0, 0, None, None, None), (None, 0, None, None, 0), (2, 0, None, None, None), (None, None, 0, 1, None), (None, None, 1, 2, None), (None, 0, None, 2, None), (None, 0, 2, None, None), (0, 1, None, None, None), (None, 2, None, 2, None), (None, 2, 2, None, None), (None, 1, None, 1, None), (None, None, 1, None, 0), (2, None, None, None, 2), (2, 2, None, None, None), (2, None, None, 0, None), (2, None, 0, None, None), (None, 1, None, 2, None), (None, 1, 2, None, None), (0, None, 1, None, None), (0, None, None, None, 1), (None, None, None, 0, 1), (None, None, 0, None, 1), (None, 2, None, 1, None), (None, 0, None, None, 2), (None, None, 1, None, 1), (2, None, 1, None, None), (2, None, None, None, 1), (None, None, 0, 2, None), (1, None, None, None, 0), (None, 1, None, None, 2), (None, 0, 1, None, None), (0, None, None, None, 2), (None, 2, None, None, 2), (0, None, None, None, 0), (None, None, 0, 0, None), (None, None, 2, 2, None), (None, None, None, 0, 0), (None, None, 0, None, 0), (None, 2, None, 0, None), (None, 2, 0, None, None), (1, None, 1, None, None), (None, None, 1, None, 2), (2, None, None, None, 0), (0, 2, None, None, None), (1, None, None, 0, None), (1, None, None, None, 1), (1, None, 0, None, None), (None, None, 1, 0, None), (None, 1, None, 0, None), (None, 1, 0, None, None), (None, None, 2, 1, None), (None, 2, None, None, 1), (1, 1, None, None, None), (None, None, None, 2, 2), (1, None, None, None, 2), (0, None, None, 2, None), (0, None, 2, None, None), (None, 1, 1, None, None), (None, None, None, 1, 0), (None, None, 2, None, 2), (None, 1, None, None, 0), (None, None, 2, 0, None), (1, 0, None, None, None), (None, 2, None, None, 0)}
        

        【讨论】:

          猜你喜欢
          • 2014-08-01
          • 1970-01-01
          • 2020-08-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-03-26
          • 1970-01-01
          相关资源
          最近更新 更多