Python:嵌套循环的程序不起作用

时间:2015-07-03 15:06:21

标签: python permutation

此程序需要通过使用此规则交换元素来查找列表的所有排列 - 交换最后一个元素直到它成为第一个(例如1,2,3,4变为1,2,4,3等等,直到4 ,1,2,3),当它成为第一个元素时,你需要切换最后2个元素并在相反的方向做同样的事情(交换第一个元素,直到它变为最后一个然后交换前2个元素并重复),这是也被称为Steinhaus - Johnson - Trotter算法。出于某种原因,我的实现并不是在Python中工作,我想知道为什么以及我需要做些什么来使它工作。

编辑:通过"不工作"我的意思是程序只打印list1而不执行任何其他操作,程序只能通过" kill"它意味着它被卡在无限循环中(这可以通过在将list1附加到all_permutations之后打印all_permutations来证明。)

list1 = [0, 1, 2, 3] #list that will be swapped
x = 3  #this is used for swapping

all_permutations = [] #list where permutations will be added

print(list1) #print list1 because it is the first permutation

while len(all_permutations) != 23:  #loop until all permutations are found (4! = 24 but since list1 is already 1 permutation we only need 23)
    x -= 1
    list1[x], list1[x+1] = list1[x+1], list1[x]
    all_permutations.append(list1)   

                               #code above swaps the last element until it becomes 1st in the list
    if x == 0:  #if last element becomes 1st
        list1[2], list1[3] = list1[3], list1[2]  #swap last 2 elements
        while x != 3:  #loop which swaps 1st element until it becomes the last element
            if len(all_permutations) == 23:  
                break
            else:
                continue
            x += 1
            list1[x-1], list1[x] = list1[x], list1[x-1]  
            all_permutations.append(list1)


        list1[0], list1[1] = list1[1], list1[0] #when loop is over (when 1st element becomes last) switch first 2 elements
        all_permutations.append(list1)


    else:
        continue



print(all_permutations) #print all permutations

3 个答案:

答案 0 :(得分:2)

while x != 3:  
    if len(all_permutations) == 23:  
        break
    else:
        continue

此处的这段代码将导致无限循环。如果all_permutations的长度不是23,则会触及continue语句。这会将程序发送回循环的开头,而不会修改xall_permutations

我相信你在这里寻找的是pass,它什么都不做。 continue将回到循环的开头。因此,要修复程序的这一部分,您实际上可以完全摆脱else,因为break无论如何都会退出循环。

while x != 3:  
    if len(all_permutations) == 23:  
        break
    x += 1
    list1[x-1], list1[x] = list1[x], list1[x-1]  
    all_permutations.append(list1)

或者你可以完全取消if

while x != 3 or len(all_permutations) != 23:  
    x += 1
    list1[x-1], list1[x] = list1[x], list1[x-1]  
    all_permutations.append(list1)

答案 1 :(得分:0)

您正在向all_permutations添加对同一列表对象的多个引用,并且每次循环时都会修改该列表对象。而是添加列表的副本,以便您拥有一组不同的排列。

all_permutations.append(list1[:])

这是一个错误;无限循环是由于IanAuld指出的问题。

答案 2 :(得分:0)

http://pastebin.com/bY7ZznR1处的新代码陷入无限循环的原因是,当masterData.addAll(wrapper.getFiles()); 在内部len(all_permutations) == 23循环中变为True时,您会在第30行附加另一个列表。当控制到达外循环while的顶部时,循环继续执行。

这很容易修复,但是你的算法不太正确。我已经修改了你的代码以生成任意大小的列表的排列,并注意到它为长度为3或4的列表提供了正确的结果,但是对于长度为2或5的列表则没有;我没有费心去测试其他尺寸。

FWIW,这是一个实现Steinhaus - Johnson - Trotter算法的递归版本的程序。如果您想改进迭代算法,可能会发现它很有用。

len(all_permutations) == 24

<强>输出

#!/usr/bin/env python

''' Generate permutations using the Steinhaus - Johnson - Trotter algorithm

    This generates permutations in the order known to bell ringers as
    "plain changes".
    See https://en.wikipedia.org/wiki/Steinhaus%E2%80%93Johnson%E2%80%93Trotter_algorithm

    From http://stackoverflow.com/q/31209826/4014959

    Written by PM 2Ring 2015.07.03
'''

import sys

def sjt_permute(items):
    num = len(items)
    if num == 1:
        yield items[:1]
        return

    last = items[-1:]
    uprange = range(num)
    dnrange = uprange[::-1]
    descend = True
    for perm in sjt_permute(items[:-1]):
        rng = dnrange if descend else uprange
        for i in rng:
            yield perm[:i] + last + perm[i:]
        descend = not descend

def main():
    num = int(sys.argv[1]) if len(sys.argv) > 1 else 4
    items = range(num)
    for p in sjt_permute(items):
        print(p)

if __name__ == '__main__':
    main()