melasiam
melasiam

Reputation: 33

Python : Generating cyclic permutations code (An unexpected code error to be clarified)

I didn't manage to correct a code I thought it would work for sure. Any advice to make the code functional is accepted. Expected outputs of the following code is a list containing a cyclic permuation of the list

l = [1,2,3,4] (i.e : [[4, 1, 2, 3],[3, 4, 1, 2],[2, 3, 4, 1],[1, 2, 3, 4]])

Although what I get is : [[2, 3, 4, 1]]

The code :

def cycGen(l):
    L=[]
    while not(l in L) :
        L.append(l)
        for i in range(len(l)):
            if l[i] == len(l) :
                l[i]=1
            else :
                l[i] = 1 + l[i] 
    return L
print(cycGen([1,2,3,4]))

Another variation of the solution is to consider the following code wich seems unfortunatly not working either :

def cycGen(l):
    L=[]
    for k in range(len(l)):
        L.append(l)
        for i in range(len(l)):
            if l[i] == len(l) :
                l[i]=1
            else :
                l[i] = 1 + l[i]   
    return L

Help me with your generous knowlege sharing please.

Upvotes: 3

Views: 2059

Answers (5)

ceremcem
ceremcem

Reputation: 4350

You can use collections.deque:

from collections import deque
a = [1, 2, 3, 4]

d = deque(a)
for _ in range(len(a)):
    d.rotate()
    print(list(d))

Which gives you the output:

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

As mentioned in Efficient way to shift a list in python

Upvotes: 4

ssm
ssm

Reputation: 5373

An easy way is just:

In [12]: x = [1,2,3,4]

In [13]: [x[i:]+x[:i] for i in range(len(x))]
Out[13]: [[1, 2, 3, 4], [2, 3, 4, 1], [3, 4, 1, 2], [4, 1, 2, 3]]

Upvotes: 1

f.rodrigues
f.rodrigues

Reputation: 3587

You could do this using a generator too:

a = [1, 2, 3, 4]

def next_pos(max):
    i = 0
    while True:
        for n in xrange(max):
            yield n + i
        i += 1

pos = next_pos(len(a))

b = []
for i in xrange(len(a)):
    n = []
    for j in xrange(len(a)):
        m = pos.next()
        if m >= len(a):
            m -= len(a)
        n.append(a[m])
    b.append(n)

print b

output:

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

Upvotes: 0

mshsayem
mshsayem

Reputation: 18008

Here is an easy way:

>>> def cycGen(l):
        size = len(l)
        return [[l[(i+j)%size] for i in range(size)] for j in range(size)]

>>> l = [1,2,3,4]
>>> print cycGen(l)
[[1, 2, 3, 4], [2, 3, 4, 1], [3, 4, 1, 2], [4, 1, 2, 3]]

Upvotes: 0

jwodder
jwodder

Reputation: 57510

In your first code sample, the line L.append(l) appends a "reference" (loosely speaking) to the list l to the end of L, rather than appending a copy as you seem to be expecting. Thus, when l is later modified, the reference to it contained in L is modified as well, and so when l in L is tested, l will equal the reference to itself in L, and so the loop will end. The same basic problem causes your second code sample to return multiples of the same list rather than several different lists.

To store a copy of l at the current point in time in L instead, use L.append(l[:]).

Upvotes: 0

Related Questions