欧拉项目编号24

时间:2016-09-12 00:37:57

标签: python-2.7

Python 2.7.9

您好我遇到了python如何处理我的排列算法的一些问题。

所以我希望我的函数采用 set_list = [1,2,3,4] 并返回该列表的所有排列。

这是我的想法。从左向右移动,从 set_list 的索引值0,1开始,使用 set_list [index +]的值翻转 set_list [index] 的值1] ,了解当你到达终点时,用 set_list [-1] 翻转 set_list [0] 。我以为这是gucci。

解 前进

1234
2134
2314
2341
1342
3142
3412
3421
1423
4123
4213
4231

然后,想法只是反向排序先前的子列表以获得所有可能的排列。

解决方案反向 4321 4312 4132 1432 2431 2413 2143 1243 3241 3214 3124 1324

我的python笔记

x = [1,2,3,4]
print(x)
  j    k      k    j
x[0],x[1] = x[1],x[0]
print(x)
x[1],x[2] = x[2],x[1]
print(x)
x[2],x[3] = x[3],x[2]
print(x)
x[3],x[0] = x[0],x[3]
print(x)
x[0],x[1] = x[1],x[0]
print(x)
x[1],x[2] = x[2],x[1]
print(x)
x[2],x[3] = x[3],x[2]
print(x)
x[3],x[0] = x[0],x[3]
print(x)
x[0],x[1] = x[1],x[0]
print(x)
x[1],x[2] = x[2],x[1]
print(x)
x[2],x[3] = x[3],x[2]
print(x)
x[3],x[0] = x[0],x[3]
print(x)

代码返回:

[1, 2, 3, 4]
[2, 1, 3, 4]
[2, 3, 1, 4]
[2, 3, 4, 1]
[1, 3, 4, 2]
[3, 1, 4, 2]
[3, 4, 1, 2]
[3, 4, 2, 1]
[1, 4, 2, 3]
[4, 1, 2, 3]
[4, 2, 1, 3]
[4, 2, 3, 1]
[1, 2, 3, 4]

因此有很多原因递归使用此函数不起作用(我不明白为什么):

def set_return(__LIST__,j,k):
    __LIST__[j],__LIST__[k]=__LIST__[k],__LIST__[j]
    return(__LIST__)

所以我决定尝试sudo-bullshit-hack一个解决方案,并且只是成功地成功地拔掉了我的头发。

第1步) 根据列表 x 的特征创建包含j,k垂直列表值的列表应该不是那么难吗?

x = [1,2,3,4]
set_0 = range(0,len(x))*(len(x)-1)
set_1 = set_0[1:len(set_0)]+[set_0[0]]

代码返回:

>>> set_0
[0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3]
>>> set_1
[1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0]
>>> 

步骤2)

def shift(__LIST__,a,b):
    j = int(__LIST__[a])
    k = int(__LIST__[b])
    __LIST__[a] = k
    __LIST__[b] = j
    return(__LIST__)

代码输出:

>>> 
[1, 2, 3, 4]
[2, 1, 3, 4]
[2, 3, 1, 4]
[2, 3, 4, 1]
[1, 3, 4, 2]
[3, 1, 4, 2]
[3, 4, 1, 2]
[3, 4, 2, 1]
[1, 4, 2, 3]
[4, 1, 2, 3]
[4, 2, 1, 3]
[4, 2, 3, 1]
[1, 2, 3, 4]
>>> set_0
[0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3]
>>> set_1
[1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0]
>>> shift([1, 2, 3, 4],0,1)
[2, 1, 3, 4]
>>> shift([2, 1, 3, 4],1,2)
[2, 3, 1, 4]
>>> shift([2, 3, 1, 4],2,3)
[2, 3, 4, 1]
>>> shift([2, 3, 4, 1],3,0)
[1, 3, 4, 2]
>>>

然后我用这个:

chi = [1,2,3,4]
set_0 = range(0,len(chi))*(len(chi)-1)
set_1 = set_0[1:len(set_0)]+[set_0[0]]
to_return=[]
x = [1,2,3,4]
for i in range(len(set_0)):
    insert=shift(x,set_0[i],set_1[i])
    to_return.append(insert)
    x = insert

得到:

[[1, 2, 3, 4], 
[1, 2, 3, 4], 
[1, 2, 3, 4], 
[1, 2, 3, 4], 
[1, 2, 3, 4], 
[1, 2, 3, 4], 
[1, 2, 3, 4], 
[1, 2, 3, 4], 
[1, 2, 3, 4], 
[1, 2, 3, 4], 
[1, 2, 3, 4], 
[1, 2, 3, 4]]

有更简单的方法......是的。我可以“保护” x 插入,或者甚至可能使用 list() ... face palm。无论如何发布。请享用。

2 个答案:

答案 0 :(得分:1)

您在代码末尾遇到的问题是,您的所有insert值都是对同一列表x的引用,shift函数会对其进行修改。您只会在[1, 2, 3, 4]列表中看到to_return值,因为这是x的最终值。如果您在循环播放时打印x,则会看到其他排列,但在to_return中存储引用时,如果稍后修改x,则不会保留该值。

与此比较:

x = [1, 2]
y = [x, x, x, x]   # y contains several references to the list x
print(y)    # prints [[1, 2], [1, 2], [1, 2], [1, 2]]
x[0] = 0    # modify x in place
print(y)    # prints [[0, 2], [0, 2], [0, 2], [0, 2]], all the 1's are gone!

要解决此问题,您可以先复制列表,然后再将其附加到to_return。稍后再次修改x时,副本不会更改。 (另一种解决方案是更改shift以返回新列表而不更改旧列表,但我将继续探索该选项。)当您存储副本时,您甚至不会需要关注shift的返回值,您可以直接使用x

for i in range(len(set_0)):
    shift(x,set_0[i],set_1[i])   # ignore the return value, which is another reference to x
    to_return.append(x[:])   # append a copy of x

切片x[:]是一种复制列表的简洁方法。如果你想要更明确一些(以一些额外的字符为代价),你可以使用list(x)。这两个版本都很容易被经验丰富的Python程序员理解为副本。

在我完成这个答案之前,我想提出一些与您所询问的问题有些无关的其他建议。

首先,您的算法实际上并未找到您提供的列表的所有排列。例如,[4, 3, 2, 1]永远不会出现(也不会出现4之前3直接出现的任何排列。因此,即使我上面提出的代码在做你想做的事情上“有效”,也可能在更大的意义上没有做正确的事情。

其次是风格问题。 Python允许您根据自己的喜好命名变量,但使用某些名称是一个非常糟糕的主意。在你的几个函数中,你使用名称__LIST__,这是一个非常糟糕的参数名称。首先,为解释器保留双下划线名称。在将来的某个版本中,Python可能会在名称__LIST__中存储一些特殊值(覆盖您正在使用它的任何内容)。或者它可能期望该名称保存某种特定类型的值,并且如果您在其中存储其他内容,则以某种方式中断。所以不要对任意变量使用双下划线!

即使我们忽略了双重下划线,__LIST__也不是一个好名字,因为它很长很难打字。虽然更明确的名称通常是好的(例如number_of_things可能比n更好),但您必须平衡这一点,并且易于阅读和输入。使用list可能不明智,因为这是内置类型的名称,但lst是它的一个非常常见的缩写。

说到名字,最重要的是要保持一致。如果您将ab用于一次性变量并不重要,但是当您有时使用这些变量时会更加混乱,有时则会使用j和{{1} (他们的意思没有任何明显的区别)。

答案 1 :(得分:0)

def factorial(n):
    c=1
    for i in range(1,n+1):
        c*=i
    return(c)

def set_start(LIST):
    to_return=[]
    for i in range(len(LIST)):
        insert=[]
        for x in range(len(LIST)):
            if LIST[i]!=LIST[x]:
                insert.append(LIST[x])
        to_return.append(insert)
    return(to_return)

def set_builder(NESTED_LIST):
    to_return=[]
    for i in range(len(NESTED_LIST)):
        to_return.append(set_start(NESTED_LIST[i]))
    return(to_return)

def set_chain(NESTED_LIST):
    to_return=[]
    for i in range(len(NESTED_LIST)):
        to_return+=NESTED_LIST[i]
    return(to_return)

def set_expand(SET):
    to_return=[]
    for i in range(len(SET)):
        to_return+=[SET[i]]*factorial(len(SET)-1)
    return(to_return)

def set_rotation(SET):
    set_0 = range(0,len(SET)-1,2)
    set_1 = range(1,len(SET),2)
    to_return=[]
    for i in range(len(set_0)):
        to_return+=[SET[set_1[i]],SET[set_0[i]]]
    return(to_return)

def recursive_chain(SET):
    sub_set_lengths=[]
    for i in range(len(SET)):
        sub_set_lengths.append(len(SET[i]))
    sub_set_lengths = sorted(list(set(sub_set_lengths)),reverse=True)
    to_return=[]
    for i in range(len(sub_set_lengths)):
        insert=[]
        for x in range(len(SET)):
            if sub_set_lengths[i]==len(SET[x]):
                insert+=SET[x]
        to_return.append(insert)
    return(to_return)

def recursive_return(to_return):
    to_return = [to_return]
    initialize = set_start(to_return[-1])
    while len(to_return[-1])!=2:
        to_return+=initialize
        to_chain = list(set_builder(list(initialize)))
        to_pass = list(set_chain(list(to_chain)))
        initialize = list(to_pass)
    for i in range(len(to_return)):
        if len(to_return[i])!=2:
            to_return[i]=set_expand(to_return[i])
    to_return = recursive_chain(to_return)
    to_return+=[set_rotation(to_return[-1])]
    return(to_return)


def PERMUTATIONS(SET):
    to_return=[]
    to_pop = recursive_return(SET) 
    while to_pop[-1]!=[]:
        insert=[]
        for i in range(len(SET)):
            insert.append(to_pop[i][0])
        to_return.append(insert)
        for i in range(len(SET)):
            to_pop[i].pop(0)
    return(to_return)