user13541811
user13541811

Reputation:

Moving elements in a list to the last

I'm trying to move elements in a list such that the first two elements will always be appended to the last in reverse order until the list is the same one I started with. For example for

l = [1,2,3,4,5]

I should get

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

so six iterations will do.

Currently I have the following code

l = [1,2,3,4,5] 
for i, j in zip(l, l[1:]): 
   l.append(l.pop(l.index(j)))  
   l.append(l.pop(l.index(i))) 

What I was trying to do was to loop two consecutive elements and pop them and append to them as last two in the list in reversed order. This doesn't seem to work since printing the list at each step returns

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

so only the first iteration seems to work. What should I modify here?

Upvotes: 0

Views: 230

Answers (3)

Alex Mandelias
Alex Mandelias

Reputation: 517

An easy way to do it with append() and pop():

ls = [1, 2, 3, 4, 5]
newls = ls[2:] + [ls[1], ls[0]]

while newls != ls:
    newls.append(newls.pop(1))
    newls.append(newls.pop(0))
    print(newls)

Upvotes: 0

Kelly Bundy
Kelly Bundy

Reputation: 27588

Here's a direct way to compute the steps needed for n distinct values:

(n-1) * (n+1) // 4 if n % 2 else n

Demo comparing an actually-do-it solution with my formula solution:

def naive_count(n):
    initial = list(range(n))
    a = initial.copy()
    steps = 0
    while True:
        a = a[2:] + a[1::-1]
        steps += 1
        if a == initial:
            return steps

def compute_count(n):
    return (n-1) * (n+1) // 4 if n % 2 else n

for n in range(2, 14):
    print(f'{n=}:', naive_count(n), compute_count(n))

Output:

n=2: 2 2
n=3: 2 2
n=4: 4 4
n=5: 6 6
n=6: 6 6
n=7: 12 12
n=8: 8 8
n=9: 20 20
n=10: 10 10
n=11: 30 30
n=12: 12 12
n=13: 42 42

And some larger ones:

for n in range(100, 110):
    print(f'{n=}:', naive_count(n), compute_count(n))
n=100: 100 100
n=101: 2550 2550
n=102: 102 102
n=103: 2652 2652
n=104: 104 104
n=105: 2756 2756
n=106: 106 106
n=107: 2862 2862
n=108: 108 108
n=109: 2970 2970

And a larger check:

print(all(naive_count(n) == compute_count(n)
          for n in range(2, 400)))
True

But don't expect me to explain the formula for odd n :-P

Upvotes: 2

SimfikDuke
SimfikDuke

Reputation: 1148

l = [1, 2, 3, 4, 5]
c = l.copy()

while True:
    l = l[2:] + [l[1], l[0]]
    print(l)
    if l == c:
        break

Upvotes: 8

Related Questions