簡體   English   中英

python 中的遞歸排列

[英]permutations with recursion in python

我的任務是編寫一個代碼,該代碼采用未定義數字列表並使用遞歸打印帶有第一個常量的所有排列,這是我編寫的代碼,但我不知道問題出在哪里

 portnames = ["PAN", "AMS", "CAS", "NYC", "HEL"]


def permutations(route, ports):
    for items in ports:
        route.append(ports)
        ports = ports[:items]+ports[items+1:]
        permutations(route, ports)
    print(' '.join([portnames[i] for i in route]))


permutations([0], list(range(1, len(portnames))))

注意:function 必須包含

我們可以使用歸納推理編寫任何可迭代tpermutations(t) -

  1. 如果t為空,則產生空排列, ()
  2. (感性) t至少有一個元素。 對於所有p的遞歸子問題permutations(t[1:]) ,對於所有iinserts(p, t[0]) ,產生i
def permutations(t):
  if not t:
    yield ()                       # 1. empty t
  else:
    for p in permutations(t[1:]):  # 2. at least one element
      for i in inserts(p, t[0]):
        yield i

其中inserts(t, x)也可以使用歸納推理來編寫 -

  1. 如果輸入t為空,則產生最終插入, (x)
  2. (感性) t至少有一個元素。 yield x附加到t並且對於所有i遞歸子問題inserts(t[1:], x) yield t[0]附加到i
def inserts(t, x):
  if not t:
    yield (x,)                       # 1. empty t
  else:
    yield (x, *t)                    # 2. at least one element
    for i in inserts(t[1:], x):
      yield (t[0], *i)
t = ("🔴","🟢","🔵","🟡")
for p in permutations(t):
  print("".join(p))
🔴🟢🔵🟡
🟢🔴🔵🟡
🟢🔵🔴🟡
🟢🔵🟡🔴
🔴🔵🟢🟡
🔵🔴🟢🟡
🔵🟢🔴🟡
🔵🟢🟡🔴
🔴🔵🟡🟢
🔵🔴🟡🟢
🔵🟡🔴🟢
🔵🟡🟢🔴
🔴🟢🟡🔵
🟢🔴🟡🔵
🟢🟡🔴🔵
🟢🟡🔵🔴
🔴🟡🟢🔵
🟡🔴🟢🔵
🟡🟢🔴🔵
🟡🟢🔵🔴
🔴🟡🔵🟢
🟡🔴🔵🟢
🟡🔵🔴🟢
🟡🔵🟢🔴

Python 對生成器有強大的支持,並使用yield from..提供委托。 我們可以簡化上述定義,同時保持完全相同的行為 -

def permutations(t):
  if not t:
    yield ()
  else:
    for p in permutations(t[1:]):
      yield from inserts(p, t[0])  # <-
def inserts(t, x):
  if not t:
    yield (x,)
  else:
    yield (x, *t)
    yield from map(lambda r: (t[0], *r), inserts(t[1:], x)) # <-

生成器非常適合組合數學,因為使用它們是自然而直接的 -

# find all permutations where red is left of green
for p in permutations(t):
  if p.index("🔴") < p.index("🟢"):
    print("".join(p))
🔴🟢🔵🟡
🔴🔵🟢🟡
🔵🔴🟢🟡
🔴🔵🟡🟢
🔵🔴🟡🟢
🔵🟡🔴🟢
🔴🟢🟡🔵
🔴🟡🟢🔵
🟡🔴🟢🔵
🔴🟡🔵🟢
🟡🔴🔵🟢
🟡🔵🔴🟢
# find all permutations where blue and yellow are adjacent
for p in permutations(t):
  if abs(p.index("🔵") - p.index("🟡")) == 1:
    print("".join(p))
🔴🟢🔵🟡
🟢🔴🔵🟡
🟢🔵🟡🔴
🔴🔵🟡🟢
🔵🟡🔴🟢
🔵🟡🟢🔴
🔴🟢🟡🔵
🟢🔴🟡🔵
🟢🟡🔵🔴
🔴🟡🔵🟢
🟡🔵🔴🟢
🟡🔵🟢🔴

此外,生成器可以隨時暫停/停止,允許我們跳過潛在的數百萬次計算以解決非常大的問題 -

# which permutation is in rainbow order?
for (n, p) in enumerate(permutations(t)):
  if p == ("🔴", "🟡", "🟢", "🔵"):
    print(f"permutation {n} is in rainbow order, {p}")
    break  # <- stops generating additional permutations
permutation 16 is in rainbow order, ('🔴', '🟡', '🟢', '🔵')

我們現在對您的portnames數據使用permutations -

portnames = ["PAN", "AMS", "CAS", "NYC", "HEL"]
for x in permutations(portnames):
  print(x)
('PAN', 'AMS', 'CAS', 'NYC', 'HEL')
('AMS', 'PAN', 'CAS', 'NYC', 'HEL')
('AMS', 'CAS', 'PAN', 'NYC', 'HEL')
('AMS', 'CAS', 'NYC', 'PAN', 'HEL')
('AMS', 'CAS', 'NYC', 'HEL', 'PAN')
('PAN', 'CAS', 'AMS', 'NYC', 'HEL')
('CAS', 'PAN', 'AMS', 'NYC', 'HEL')
('CAS', 'AMS', 'PAN', 'NYC', 'HEL')
('CAS', 'AMS', 'NYC', 'PAN', 'HEL')
('CAS', 'AMS', 'NYC', 'HEL', 'PAN')
('PAN', 'CAS', 'NYC', 'AMS', 'HEL')
('CAS', 'PAN', 'NYC', 'AMS', 'HEL')
('CAS', 'NYC', 'PAN', 'AMS', 'HEL')
('CAS', 'NYC', 'AMS', 'PAN', 'HEL')
('CAS', 'NYC', 'AMS', 'HEL', 'PAN')
('PAN', 'CAS', 'NYC', 'HEL', 'AMS')
('CAS', 'PAN', 'NYC', 'HEL', 'AMS')
('CAS', 'NYC', 'PAN', 'HEL', 'AMS')
('CAS', 'NYC', 'HEL', 'PAN', 'AMS')
('CAS', 'NYC', 'HEL', 'AMS', 'PAN')
('PAN', 'AMS', 'NYC', 'CAS', 'HEL')
('AMS', 'PAN', 'NYC', 'CAS', 'HEL')
('AMS', 'NYC', 'PAN', 'CAS', 'HEL')
('AMS', 'NYC', 'CAS', 'PAN', 'HEL')
('AMS', 'NYC', 'CAS', 'HEL', 'PAN')
('PAN', 'NYC', 'AMS', 'CAS', 'HEL')
('NYC', 'PAN', 'AMS', 'CAS', 'HEL')
('NYC', 'AMS', 'PAN', 'CAS', 'HEL')
('NYC', 'AMS', 'CAS', 'PAN', 'HEL')
('NYC', 'AMS', 'CAS', 'HEL', 'PAN')
('PAN', 'NYC', 'CAS', 'AMS', 'HEL')
('NYC', 'PAN', 'CAS', 'AMS', 'HEL')
('NYC', 'CAS', 'PAN', 'AMS', 'HEL')
('NYC', 'CAS', 'AMS', 'PAN', 'HEL')
('NYC', 'CAS', 'AMS', 'HEL', 'PAN')
('PAN', 'NYC', 'CAS', 'HEL', 'AMS')
('NYC', 'PAN', 'CAS', 'HEL', 'AMS')
('NYC', 'CAS', 'PAN', 'HEL', 'AMS')
('NYC', 'CAS', 'HEL', 'PAN', 'AMS')
('NYC', 'CAS', 'HEL', 'AMS', 'PAN')
('PAN', 'AMS', 'NYC', 'HEL', 'CAS')
('AMS', 'PAN', 'NYC', 'HEL', 'CAS')
('AMS', 'NYC', 'PAN', 'HEL', 'CAS')
('AMS', 'NYC', 'HEL', 'PAN', 'CAS')
('AMS', 'NYC', 'HEL', 'CAS', 'PAN')
('PAN', 'NYC', 'AMS', 'HEL', 'CAS')
('NYC', 'PAN', 'AMS', 'HEL', 'CAS')
('NYC', 'AMS', 'PAN', 'HEL', 'CAS')
('NYC', 'AMS', 'HEL', 'PAN', 'CAS')
('NYC', 'AMS', 'HEL', 'CAS', 'PAN')
('PAN', 'NYC', 'HEL', 'AMS', 'CAS')
('NYC', 'PAN', 'HEL', 'AMS', 'CAS')
('NYC', 'HEL', 'PAN', 'AMS', 'CAS')
('NYC', 'HEL', 'AMS', 'PAN', 'CAS')
('NYC', 'HEL', 'AMS', 'CAS', 'PAN')
('PAN', 'NYC', 'HEL', 'CAS', 'AMS')
('NYC', 'PAN', 'HEL', 'CAS', 'AMS')
('NYC', 'HEL', 'PAN', 'CAS', 'AMS')
('NYC', 'HEL', 'CAS', 'PAN', 'AMS')
('NYC', 'HEL', 'CAS', 'AMS', 'PAN')
('PAN', 'AMS', 'CAS', 'HEL', 'NYC')
('AMS', 'PAN', 'CAS', 'HEL', 'NYC')
('AMS', 'CAS', 'PAN', 'HEL', 'NYC')
('AMS', 'CAS', 'HEL', 'PAN', 'NYC')
('AMS', 'CAS', 'HEL', 'NYC', 'PAN')
('PAN', 'CAS', 'AMS', 'HEL', 'NYC')
('CAS', 'PAN', 'AMS', 'HEL', 'NYC')
('CAS', 'AMS', 'PAN', 'HEL', 'NYC')
('CAS', 'AMS', 'HEL', 'PAN', 'NYC')
('CAS', 'AMS', 'HEL', 'NYC', 'PAN')
('PAN', 'CAS', 'HEL', 'AMS', 'NYC')
('CAS', 'PAN', 'HEL', 'AMS', 'NYC')
('CAS', 'HEL', 'PAN', 'AMS', 'NYC')
('CAS', 'HEL', 'AMS', 'PAN', 'NYC')
('CAS', 'HEL', 'AMS', 'NYC', 'PAN')
('PAN', 'CAS', 'HEL', 'NYC', 'AMS')
('CAS', 'PAN', 'HEL', 'NYC', 'AMS')
('CAS', 'HEL', 'PAN', 'NYC', 'AMS')
('CAS', 'HEL', 'NYC', 'PAN', 'AMS')
('CAS', 'HEL', 'NYC', 'AMS', 'PAN')
('PAN', 'AMS', 'HEL', 'CAS', 'NYC')
('AMS', 'PAN', 'HEL', 'CAS', 'NYC')
('AMS', 'HEL', 'PAN', 'CAS', 'NYC')
('AMS', 'HEL', 'CAS', 'PAN', 'NYC')
('AMS', 'HEL', 'CAS', 'NYC', 'PAN')
('PAN', 'HEL', 'AMS', 'CAS', 'NYC')
('HEL', 'PAN', 'AMS', 'CAS', 'NYC')
('HEL', 'AMS', 'PAN', 'CAS', 'NYC')
('HEL', 'AMS', 'CAS', 'PAN', 'NYC')
('HEL', 'AMS', 'CAS', 'NYC', 'PAN')
('PAN', 'HEL', 'CAS', 'AMS', 'NYC')
('HEL', 'PAN', 'CAS', 'AMS', 'NYC')
('HEL', 'CAS', 'PAN', 'AMS', 'NYC')
('HEL', 'CAS', 'AMS', 'PAN', 'NYC')
('HEL', 'CAS', 'AMS', 'NYC', 'PAN')
('PAN', 'HEL', 'CAS', 'NYC', 'AMS')
('HEL', 'PAN', 'CAS', 'NYC', 'AMS')
('HEL', 'CAS', 'PAN', 'NYC', 'AMS')
('HEL', 'CAS', 'NYC', 'PAN', 'AMS')
('HEL', 'CAS', 'NYC', 'AMS', 'PAN')
('PAN', 'AMS', 'HEL', 'NYC', 'CAS')
('AMS', 'PAN', 'HEL', 'NYC', 'CAS')
('AMS', 'HEL', 'PAN', 'NYC', 'CAS')
('AMS', 'HEL', 'NYC', 'PAN', 'CAS')
('AMS', 'HEL', 'NYC', 'CAS', 'PAN')
('PAN', 'HEL', 'AMS', 'NYC', 'CAS')
('HEL', 'PAN', 'AMS', 'NYC', 'CAS')
('HEL', 'AMS', 'PAN', 'NYC', 'CAS')
('HEL', 'AMS', 'NYC', 'PAN', 'CAS')
('HEL', 'AMS', 'NYC', 'CAS', 'PAN')
('PAN', 'HEL', 'NYC', 'AMS', 'CAS')
('HEL', 'PAN', 'NYC', 'AMS', 'CAS')
('HEL', 'NYC', 'PAN', 'AMS', 'CAS')
('HEL', 'NYC', 'AMS', 'PAN', 'CAS')
('HEL', 'NYC', 'AMS', 'CAS', 'PAN')
('PAN', 'HEL', 'NYC', 'CAS', 'AMS')
('HEL', 'PAN', 'NYC', 'CAS', 'AMS')
('HEL', 'NYC', 'PAN', 'CAS', 'AMS')
('HEL', 'NYC', 'CAS', 'PAN', 'AMS')
('HEL', 'NYC', 'CAS', 'AMS', 'PAN')

您可以為此使用 itertools 模塊。

基本上,在進行排列組合時,這是一個非常有用的地方。


import itertools

portnames = ["PAN", "AMS", "CAS", "NYC", "HEL"]


x = itertools.permutations(portnames)
y = list(x)

# or this is you want to inspect the loop
# y = []
# for i in x:
#     y.append(i)

y

結果是一個大列表:

[('PAN', 'AMS', 'CAS', 'NYC', 'HEL')
('PAN', 'AMS', 'CAS', 'HEL', 'NYC')
('PAN', 'AMS', 'NYC', 'CAS', 'HEL')
('PAN', 'AMS', 'NYC', 'HEL', 'CAS')
('PAN', 'AMS', 'HEL', 'CAS', 'NYC')
('PAN', 'AMS', 'HEL', 'NYC', 'CAS')
('PAN', 'CAS', 'AMS', 'NYC', 'HEL')
('PAN', 'CAS', 'AMS', 'HEL', 'NYC')
('PAN', 'CAS', 'NYC', 'AMS', 'HEL')
('PAN', 'CAS', 'NYC', 'HEL', 'AMS')
('PAN', 'CAS', 'HEL', 'AMS', 'NYC')
('PAN', 'CAS', 'HEL', 'NYC', 'AMS')
('PAN', 'NYC', 'AMS', 'CAS', 'HEL')
('PAN', 'NYC', 'AMS', 'HEL', 'CAS')
('PAN', 'NYC', 'CAS', 'AMS', 'HEL')
('PAN', 'NYC', 'CAS', 'HEL', 'AMS')
('PAN', 'NYC', 'HEL', 'AMS', 'CAS')
('PAN', 'NYC', 'HEL', 'CAS', 'AMS')
('PAN', 'HEL', 'AMS', 'CAS', 'NYC')
('PAN', 'HEL', 'AMS', 'NYC', 'CAS')
('PAN', 'HEL', 'CAS', 'AMS', 'NYC')
('PAN', 'HEL', 'CAS', 'NYC', 'AMS')
...
..and so on

('HEL', 'NYC', 'PAN', 'CAS', 'AMS'),
 ('HEL', 'NYC', 'AMS', 'PAN', 'CAS'),
 ('HEL', 'NYC', 'AMS', 'CAS', 'PAN'),
 ('HEL', 'NYC', 'CAS', 'PAN', 'AMS'),
 ('HEL', 'NYC', 'CAS', 'AMS', 'PAN')]

附帶說明一下,雖然您的嘗試很好,但由於 output 很大並且遞歸次數很大,您可能會遇到堆棧溢出。

您可以做兩件事:

  • 增加遞歸的限制
  • 轉換為whilefor循環。

但是, itertool.permutations選項是最合適的。

暫無
暫無

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

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