簡體   English   中英

首先在Python中枚舉數量最少的3排列

[英]Enumerate 3-permutations with lowest numbers first in Python

這可以在Python中顯示[0, 1, 2, 3, 4]所有3個排列

import itertools
N = 5
for p in itertools.permutations(range(N), r=3):
    print p

#(0, 1, 2)
#(0, 1, 3)
#(0, 1, 4)
#(0, 2, 1)
#(0, 2, 3)
#(0, 2, 4)
#(0, 3, 1)
#...

但我想按以下順序枚舉它們:最低的數字優先,即:

#display 3-permutations of [0]
# (none)

#display 3-permutations of [0, 1] that haven't been displayed before
# (none)

#display 3-permutations of [0, 1, 2] that haven't been displayed before
(0, 1, 2)
(0, 2, 1)
(1, 0, 2)
(1, 2, 0)
(2, 0, 1)
(2, 1, 0)

#display 3-permutations of [0, 1, 2, 3] that haven't been displayed before
(0, 1, 3)
(0, 2, 3)
(0, 3, 1)
(0, 3, 2)
...

#display remaining 3-permutations of [0, 1, 2, 3, 4] that haven't been displayed before
...

有沒有一種方法可以以此順序快速枚舉[0,...,N-1]的3個排列?


注意:在我的用例中, N > 2000 ,所以它必須快(我也使用Cython進行其他計算以使其快,但這是另一個主題)。

編輯(由於@RoryDaulton):每個組中的順序無關緊要,我只關心分組。

這是一種非常快速的算法,幾乎不占用額外的內存。

首先,使用itertools枚舉[0, 1, 2]的3個置換。

然后,枚舉[0, 1, 2]的2個置換,並在產生每個置換之前將3插入末尾。 然后再次枚舉這些2排列,並在中間位置插入3 然后再次枚舉它們,並在開始位置插入3

然后枚舉[0, 1, 2, 3]的2個置換,並在末尾插入4 然后再次枚舉那些2排列,並在中間位置插入4 然后...

你明白了。 通過在第一代之后保存2個置換,您可以節省一些時間,因此您只需在適當的位置插入較大的值即可。

注意:我提出此算法以獲取示例中給出的3排列的確切順序。 如果組中的順序可以不同,則其他算法也是可能的,並且比我的算法更快。 我的算法可以很好地工作並完全給出指定的順序,但是它比具有不同順序的算法要慢。

在集合中搜索p可能可以優化,但是一種實現顯示自身排列的目標的方法是使用集合:

import itertools
N = 5
spam = set()
for i in range(N):
    print('new permutation', list(range(i+1)))
    for p in itertools.permutations(range(i+1), r=3):
        if p not in spam:
            print(p)
            spam.add(p)

我終於找到了一個最佳的解決方案:

for i in range(N):            # i is the biggest
    print 'biggest = %i' % i
    for j in range(i):        # j is the second
        for k in range(j):    # k is the smallest
                print i, j, k
                print j, k, i
                print k, i, j
                print j, i, k
                print k, j, i
                print i, k, j

這是輸出

biggest = 0
biggest = 1
biggest = 2
2 1 0
1 0 2
0 2 1
1 2 0
0 1 2
2 0 1
biggest = 3
3 1 0
1 0 3
0 3 1
1 3 0
0 1 3
3 0 1
3 2 0
2 0 3
0 3 2
2 3 0
0 2 3
3 0 2
3 2 1
2 1 3
1 3 2
2 3 1
1 2 3
3 1 2
biggest = 4
4 1 0
1 0 4
0 4 1
1 4 0
0 1 4
4 0 1
4 2 0
2 0 4
0 4 2
2 4 0
0 2 4
4 0 2
4 2 1
2 1 4
1 4 2
2 4 1
1 2 4
4 1 2
4 3 0
3 0 4
0 4 3
3 4 0
0 3 4
4 0 3
4 3 1
3 1 4
1 4 3
3 4 1
1 3 4
4 1 3
4 3 2
3 2 4
2 4 3
3 4 2
2 3 4
4 2 3

您的答案似乎是最好的方法,但是您可以通過使用permutations使它更緊湊(並改善排序)。

from itertools import permutations

num = 5
for i in range(2, num):
    for j in range(i):
        for k in range(j):
            for t in permutations((k, j, i)):
                print(t)

輸出

(0, 1, 2)
(0, 2, 1)
(1, 0, 2)
(1, 2, 0)
(2, 0, 1)
(2, 1, 0)
(0, 1, 3)
(0, 3, 1)
(1, 0, 3)
(1, 3, 0)
(3, 0, 1)
(3, 1, 0)
(0, 2, 3)
(0, 3, 2)
(2, 0, 3)
(2, 3, 0)
(3, 0, 2)
(3, 2, 0)
(1, 2, 3)
(1, 3, 2)
(2, 1, 3)
(2, 3, 1)
(3, 1, 2)
(3, 2, 1)
(0, 1, 4)
(0, 4, 1)
(1, 0, 4)
(1, 4, 0)
(4, 0, 1)
(4, 1, 0)
(0, 2, 4)
(0, 4, 2)
(2, 0, 4)
(2, 4, 0)
(4, 0, 2)
(4, 2, 0)
(1, 2, 4)
(1, 4, 2)
(2, 1, 4)
(2, 4, 1)
(4, 1, 2)
(4, 2, 1)
(0, 3, 4)
(0, 4, 3)
(3, 0, 4)
(3, 4, 0)
(4, 0, 3)
(4, 3, 0)
(1, 3, 4)
(1, 4, 3)
(3, 1, 4)
(3, 4, 1)
(4, 1, 3)
(4, 3, 1)
(2, 3, 4)
(2, 4, 3)
(3, 2, 4)
(3, 4, 2)
(4, 2, 3)
(4, 3, 2)

這是我之前提出的一些代碼。 它更緊湊,但是當N很大時會占用大量RAM。

from itertools import permutations

num = 5
a = [(i, 1<<i) for i in range(num)]
perms = sorted(permutations(a, 3), key=lambda t: sum(u[1] for u in t))
for t in perms:
    print(tuple(u[0] for u in t))

這將產生與上述代碼相同的輸出(以相同的順序)。


FWIW,這是Rory Daulton算法的實現 請注意,輸出順序略有不同。

 from itertools import permutations, combinations num = 5 for i in range(2, num): for u, v in combinations(range(i), 2): for t in permutations((u, v, i)): print(t) 

輸出

 (0, 1, 2) (0, 2, 1) (1, 0, 2) (1, 2, 0) (2, 0, 1) (2, 1, 0) (0, 1, 3) (0, 3, 1) (1, 0, 3) (1, 3, 0) (3, 0, 1) (3, 1, 0) (0, 2, 3) (0, 3, 2) (2, 0, 3) (2, 3, 0) (3, 0, 2) (3, 2, 0) (1, 2, 3) (1, 3, 2) (2, 1, 3) (2, 3, 1) (3, 1, 2) (3, 2, 1) (0, 1, 4) (0, 4, 1) (1, 0, 4) (1, 4, 0) (4, 0, 1) (4, 1, 0) (0, 2, 4) (0, 4, 2) (2, 0, 4) (2, 4, 0) (4, 0, 2) (4, 2, 0) (0, 3, 4) (0, 4, 3) (3, 0, 4) (3, 4, 0) (4, 0, 3) (4, 3, 0) (1, 2, 4) (1, 4, 2) (2, 1, 4) (2, 4, 1) (4, 1, 2) (4, 2, 1) (1, 3, 4) (1, 4, 3) (3, 1, 4) (3, 4, 1) (4, 1, 3) (4, 3, 1) (2, 3, 4) (2, 4, 3) (3, 2, 4) (3, 4, 2) (4, 2, 3) (4, 3, 2) 

@Uvar的帖子的抽象的生成器函數變體:

import itertools as it


def unique_permute(iterable, r=3, verbose=False):
    seen = set()
    for i, _ in enumerate(iterable):
        part = iterable[:i+1]
        if verbose: print("# Display 3-permutations of {} that haven't been displayed before".format(part))
        for p in it.permutations(part, r=r):
            if p not in seen:
                yield p
            seen.add(p)

演示版

lst = [0, 1, 2, 3, 4]
for p in unique_permute(lst, verbose=True):
    print("", p)

輸出量

# Display 3-permutations of [0] that haven't been displayed before
# Display 3-permutations of [0, 1] that haven't been displayed before
# Display 3-permutations of [0, 1, 2] that haven't been displayed before
 (0, 1, 2)
 (0, 2, 1)
 (1, 0, 2)
 (1, 2, 0)
 (2, 0, 1)
 (2, 1, 0)
# Display 3-permutations of [0, 1, 2, 3] that haven't been displayed before
 (0, 1, 3)
 (0, 2, 3)
 (0, 3, 1)
 (0, 3, 2)
 ...

@Rory Daulton的解決方案有一條襯里:

from itertools import *
a=[0,1,2,3,4]
print '\n'.join(['\n'.join([str(list(permutations(t)))  for t in list(combinations(a[:i+1],3)) if t not in list(combinations(a[:i],3))]) for i in range(2,len(a))])

輸出:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM