3

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.

mshsayem
  • 17,557
  • 11
  • 61
  • 69
melasiam
  • 33
  • 5
  • Possible duplicate https://stackoverflow.com/questions/5313900/generating-cyclic-permutations-reduced-latin-squares-in-python/48376124#48376124 – pylang Jan 22 '18 at 06:57

5 Answers5

4

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

Community
  • 1
  • 1
ceremcem
  • 3,900
  • 4
  • 28
  • 66
1

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]]
ssm
  • 5,277
  • 1
  • 24
  • 42
0

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[:]).

jwodder
  • 54,758
  • 12
  • 108
  • 124
0

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]]
mshsayem
  • 17,557
  • 11
  • 61
  • 69
0

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]]
f.rodrigues
  • 3,499
  • 6
  • 26
  • 62