2013-04-29 92 views
1

我非常喜欢初学者。我试图编写一个程序,该列表以列表中元素(1-9)的数量作为参数,然后将按字典顺序输出列表的所有排列。在程序中,它将每个排列作为一个列表添加到一个更大的列表中,该列表按顺序包含所有排列。虽然程序一般情况下并不像预期的那样工作,但我遇到的一个主要问题是使用while循环在第10行中,我希望列表在最终的排列被添加到列表中时停止编译。例如,如果我的输入参数是n = 4,则最后一个排列/元素应该是[4,3,2,1]。但是,当我运行这个程序时,该元素最后会在列表中出现三次。我不知道这是什么时候它应该终止while循环,一旦它被添加。以字典顺序生成列表的所有排列

def ourPermutations(n): 
    x=list(range(1,n+1)) 
    permList = [] 
    permList+=[x] 

    xcopy = x[:] 
    finalPerm = xcopy[::-1] 


    while x != finalPerm: 
     istar = n-2 
     while x[istar] > x[istar+1]: 
      istar -= 1 
     jstar = n-1 
     while x[jstar] < x[istar]: 
      jstar -= 1 
     x[istar],x[jstar] = x[jstar],x[istar] 
     if istar+1 == n-1: 
      x = x[:] 
     else: 
      a = x[istar+1:] 
      a = a[::-1] 
      x = x[:istar+1] + a 
     permList += [x] 

    return permList 

这是我的主要问题;然而,当我运行它时,这个程序仍然缺少元素。它不是很有效,所以如果你看到某个地方出现明显错误的地方,请随时告诉我特定线路是什么导致了我的问题。如果有帮助,这是基于在写数学8此相同的(正确)版本:

ourpermutations[n_] := (
    ourlist = {x=Range[1,n]}; 
    While[ 
     x != Reverse[Range[1,n]], 
     istar = n-1; 
     While[x[[istar]] > x[[istar+1, istar--]; 
     jstar = n; While[x[[jstar]] < x[[istar]], jstar--]; 
     x[[{istar, jstar}]] = x[[{jstar, istar}]]; 
     AppendTo[ourlist, x = Join[Take[x,istar], Reverse[Drop[x,istar]]]] 
    ]; 
    ourlist 
) 

所以这是我的Python代码应该做的事;我现在还无法做到这一点。感谢您的时间和精力。

+0

不是答案,但是'itertools.permutations()'在您不关心实现的情况下可能会有所帮助。 – 2013-04-29 04:54:18

+0

'ourPermutations(3)'应该是什么样子的输出? – Blender 2013-04-29 04:58:06

+0

谢谢,但一位教授只是让我们试试看看我们是否可以用其他语言工作。输出应该如下所示: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2], [3,2,1]] – pomzer 2013-04-29 05:01:54

回答

0

看起来您正遇到问题,因为您没有及时复制x,因此您有时在将其添加到permList后修改了x。这可以通过在while循环开始加入x = x[:]解决:

def ourPermutations(n): 
    x=list(range(1,n+1)) 
    permList = [] 
    permList+=[x] 

    xcopy = x[:] 
    finalPerm = xcopy[::-1] 

    while x != finalPerm: 
     x = x[:] 
     istar = n-2 
     while x[istar] > x[istar+1]: 
      istar -= 1 
     jstar = n-1 
     while x[jstar] < x[istar]: 
      jstar -= 1 
     x[istar],x[jstar] = x[jstar],x[istar] 
     if istar+1 == n-1: 
      x = x[:] 
     else: 
      a = x[istar+1:] 
      a = a[::-1] 
      x = x[:istar+1] + a 
     permList += [x] 

    return permList 

>>> ourPermutations(3) 
[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]] 
>>> ourPermutations(4) 
[[1, 2, 3, 4], [1, 2, 4, 3], [1, 3, 2, 4], [1, 3, 4, 2], [1, 4, 2, 3], [1, 4, 3, 2], [2, 1, 3, 4], [2, 1, 4, 3], [2, 3, 1, 4], [2, 3, 4, 1], [2, 4, 1, 3], [2, 4, 3, 1], [3, 1, 2, 4], [3, 1, 4, 2], [3, 2, 1, 4], [3, 2, 4, 1], [3, 4, 1, 2], [3, 4, 2, 1], [ 
4, 1, 2, 3], [4, 1, 3, 2], [4, 2, 1, 3], [4, 2, 3, 1], [4, 3, 1, 2], [4, 3, 2, 1]] 

稍微更“Python化”的版本可能看起来像:

def our_permutations(n): 
    x = list(range(1, n+1)) 
    perm_list = [x] 
    final_perm = x[::-1] 

    while x != final_perm: 
     x = x[:] 
     istar = n-2 
     while x[istar] > x[istar+1]: 
      istar -= 1 
     jstar = n-1 
     while x[jstar] < x[istar]: 
      jstar -= 1 
     x[istar],x[jstar] = x[jstar],x[istar] 
     if istar+1 != n-1: 
      a = x[istar+1:] 
      a = a[::-1] 
      x = x[:istar+1] + a 
     perm_list += [x] 

    return perm_list 

检查,对itertools.permutation这些功能表明,它们产生的相同的答案,所以它看起来像你的算法是正确的,除了那个小错误。

+0

是的,这现在完美。非常感谢!我仍然有点困惑,但为什么只是添加一行就改变了它。为什么它会改变permList中的x? – pomzer 2013-04-29 06:32:46

+0

@pomzer没问题,很高兴帮助!问题是,如果没有'x = x [:]'行,x仍然是对添加到'permList'的列表的引用。这是同样的原因,如果你做一些像'a = [1,2]; b = a; b [0] = 3;那么a和b都是[3,2]。 – 2013-04-29 06:35:24