【问题标题】:Generate all possible permutation functions生成所有可能的置换函数
【发布时间】:2016-11-30 03:24:05
【问题描述】:

我有兴趣在集合 S={1, 2, ..., n} 中找到排列 p:S->S。特别是所有对 i 和 j 进行置换的函数:p(i)=j 和 p(j)=i;或者让它们保持不变 p(i)=i 或 p(j)=j。

例如,如果 S={1,2,3},我应该得到类似:

p0 = [(1), (2), (3)] # p(1)=1, p(2)=2, p(3)=3
p1 = [(1,2), (3)] # p(1)=2, p(2)=1, p(3)=3
p2 = [(1,3), (2)]
p3 = [(2,3), (1)]

如果 S={1, 2, 3, 4}:

p0 = [(1), (2), (3), (4)]
p1 = [(1,2), (3,4)]
p2 = [(1,2), (3), (4)]  # p(1)=2, p(2)=1, p(3)=3, p(4)=4
p3 = [(1,3), (2,4)]
p4 = [(1,3), (2), (4)]
p5 = [(1,4), (2,3)]
p6 = [(1,4), (2), (3)]
p7 = [(1), (3), (2,4)] 
p8 = [(1), (4), (2,3)]
p9 = [(1), (2), (3,4)]

谢谢。

【问题讨论】:

  • 你试过什么?你清楚地知道itertools,一旦你知道了它,你就不难将它用于你的构建块。
  • 我认为不应该有这么多反对票,这不是关于 任意 排列,而是它们的一个特殊子集。一个有效的实现有点棘手。
  • @Kh40tiK:甚至不尝试就寻求帮助并不符合 SO 的精神。
  • 我意识到它需要一个算法。我对使用简单的 itertools 解决它的更紧凑的方法感兴趣。
  • 这看起来像你想要的:stackoverflow.com/q/18353280/5644961

标签: python list set combinatorics itertools


【解决方案1】:

假设目标是找到仅涉及二进制交换的排列。

from itertools import combinations

def opairs(li):
    if not li:
        yield []
        return
    li_cpy = li.copy()
    for h in range(1,len(li)):
        li_cpy = li[1:]
        del(li_cpy[h-1])
        for subli in opairs(li_cpy):
            yield [(li[0], li[h])] + subli

def swaps(n):
    assert n%2==0
    yield list(map(lambda _: (_,), range(n)))
    for subsize in range(1, n//2+1):
        for head in combinations(range(n), subsize*2):
            tail = []
            ihead = iter(head)
            ihead_next = next(ihead)
            for i in range(n):
                if i==ihead_next:
                    try:
                        ihead_next = next(ihead)
                    except: continue
                else:
                    tail.append((i,))
            for phead in opairs(list(head)):
                yield phead+tail

for p in swaps(4): print(p)

输出:

[(0,), (1,), (2,), (3,)]
[(0, 1), (2,), (3,)]
[(0, 2), (1,), (3,)]
[(0, 3), (1,), (2,)]
[(1, 2), (0,), (3,)]
[(1, 3), (0,), (2,)]
[(2, 3), (0,), (1,)]
[(0, 1), (2, 3)]
[(0, 2), (1, 3)]
[(0, 3), (1, 2)]

【讨论】:

    【解决方案2】:

    不确定如何以建设性的方式执行此操作,但构造所有排列并过滤掉不符合条件的排列相当简单。没有关于这个效率的cmets:

    >>> data = 'abcd'
    >>> [[data[i] for i in n] for n in it.permutations(range(len(data))) 
    ...                       if all(n[n[i]] == i for i in n)]
    [['a', 'b', 'c', 'd'],
     ['a', 'b', 'd', 'c'],
     ['a', 'c', 'b', 'd'],
     ['a', 'd', 'c', 'b'],
     ['b', 'a', 'c', 'd'],
     ['b', 'a', 'd', 'c'],
     ['c', 'b', 'a', 'd'],
     ['c', 'd', 'a', 'b'],
     ['d', 'b', 'c', 'a'],
     ['d', 'c', 'b', 'a']]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-18
      • 2019-07-19
      • 2016-01-07
      相关资源
      最近更新 更多