python homework interleaving list
Question:
The problem statement is:
Design and implement an algorithm that displays the elements of a list
by interleaving an element from the beginning and an element from the
end.
For example, input:
1 2 3 4 5 6 7 8
Output :
1 8 2 7 3 6 4 5
This is what I tried, but I don’t know what happen with elements 7 and 8:
lista = [1, 2, 3, 4, 5, 6, 7, 8]
for i in range(len(lista)):
lista.insert(2*i-1,lista.pop())
print("The list after shift is : " + str(lista))
# output:
# The list after shift is : [1, 7, 2, 8, 3, 6, 4, 5]
Answers:
The only error in you code, is that range(len(lista))
starts from 0
, not from 1
. By starting from zero, in the first iteration 2*i-1
will be 2*0-1 = -1
, and hence lista.insert(-1,lista.pop())
, which means inserting at the very end of the list (that is what index -1
means in python).
To fix your code, you just need to start the range from 1
. Actually, you are iterating too much, you can have your range just from 1 to the half of your list, like this:
lista = [1, 2, 3, 4, 5, 6, 7, 8]
for i in range(1, len(lista)//2):
lista.insert(2*i-1,lista.pop())
print("The list after shift is : " + str(lista))
# output:
# The list after shift is : [1, 8, 2, 7, 3, 6, 4, 5]
When you become more familiarized with the language, you will see that this can be accomplished much more easily.
For example, you can use the python slice syntax to achieve your goal. You slice from beginning to half , and from end to half (step of -1), then zip then together and flat.
[i for z in zip(lista[:4],lista[:-5:-1]) for i in z]
# [1, 8, 2, 7, 3, 6, 4, 5]
Another option:
import math
lista = [1, 2, 3, 4, 5, 6, 7, 8]
ans = []
for i in range(math.floor(len(lista)/2)):
ans.append(lista[i])
ans.append(lista[-i-1])
if (len(lista) % 2) != 0:
ans.append(lista(math.ceil(len(lista)/2)))
print(ans)
Technically speaking, I’d say it’s two off-by-one errors (or one off-by-one error, but from -1 to +1, you’ll see what I mean in the second paragraph). The first one is that you’re subtracting 1 when you shouldn’t. In the case when i = 0 (remember that range(n)
goes from 0
to n-1
), the insert position is being evaluated as 2*0-1
= (2*0)-1
= 0-1
= -1
(for insert()
method, that’s the last position of the original list, pushing what was there forward, so it’ll be the penultimate position of the NEW list).
But, when you remove the -1, the output becomes 8 1 7 2 6 3 5 4
, which is close to what you want, but not quite right. What’s missing is that the elements inserted should be at positions 1, 3, 5, 7, and not 0, 2, 4, 6. So, you’ll actually need to add 1.
So, the shortest change to fix your code is to change lista.insert(2*i-1,lista.pop())
to lista.insert(2*i+1,lista.pop())
.
Notice: if you put a print inside for, you’ll realize that, after changing half the elements, the output is already right. That’s because when len(lista) is 8, and you do lista.insert(x, lista.pop())
where x is bigger than 8, basically you’re removing the last element (pop) and adding it at the end, so, nothing changes. Hence, you could also change range(len(lista)) to range(len(lista)//2). Test if it’ll work when len(lista) is odd
The problem statement is:
Design and implement an algorithm that displays the elements of a list
by interleaving an element from the beginning and an element from the
end.
For example, input:
1 2 3 4 5 6 7 8
Output :
1 8 2 7 3 6 4 5
This is what I tried, but I don’t know what happen with elements 7 and 8:
lista = [1, 2, 3, 4, 5, 6, 7, 8]
for i in range(len(lista)):
lista.insert(2*i-1,lista.pop())
print("The list after shift is : " + str(lista))
# output:
# The list after shift is : [1, 7, 2, 8, 3, 6, 4, 5]
The only error in you code, is that range(len(lista))
starts from 0
, not from 1
. By starting from zero, in the first iteration 2*i-1
will be 2*0-1 = -1
, and hence lista.insert(-1,lista.pop())
, which means inserting at the very end of the list (that is what index -1
means in python).
To fix your code, you just need to start the range from 1
. Actually, you are iterating too much, you can have your range just from 1 to the half of your list, like this:
lista = [1, 2, 3, 4, 5, 6, 7, 8]
for i in range(1, len(lista)//2):
lista.insert(2*i-1,lista.pop())
print("The list after shift is : " + str(lista))
# output:
# The list after shift is : [1, 8, 2, 7, 3, 6, 4, 5]
When you become more familiarized with the language, you will see that this can be accomplished much more easily.
For example, you can use the python slice syntax to achieve your goal. You slice from beginning to half , and from end to half (step of -1), then zip then together and flat.
[i for z in zip(lista[:4],lista[:-5:-1]) for i in z]
# [1, 8, 2, 7, 3, 6, 4, 5]
Another option:
import math
lista = [1, 2, 3, 4, 5, 6, 7, 8]
ans = []
for i in range(math.floor(len(lista)/2)):
ans.append(lista[i])
ans.append(lista[-i-1])
if (len(lista) % 2) != 0:
ans.append(lista(math.ceil(len(lista)/2)))
print(ans)
Technically speaking, I’d say it’s two off-by-one errors (or one off-by-one error, but from -1 to +1, you’ll see what I mean in the second paragraph). The first one is that you’re subtracting 1 when you shouldn’t. In the case when i = 0 (remember that range(n)
goes from 0
to n-1
), the insert position is being evaluated as 2*0-1
= (2*0)-1
= 0-1
= -1
(for insert()
method, that’s the last position of the original list, pushing what was there forward, so it’ll be the penultimate position of the NEW list).
But, when you remove the -1, the output becomes 8 1 7 2 6 3 5 4
, which is close to what you want, but not quite right. What’s missing is that the elements inserted should be at positions 1, 3, 5, 7, and not 0, 2, 4, 6. So, you’ll actually need to add 1.
So, the shortest change to fix your code is to change lista.insert(2*i-1,lista.pop())
to lista.insert(2*i+1,lista.pop())
.
Notice: if you put a print inside for, you’ll realize that, after changing half the elements, the output is already right. That’s because when len(lista) is 8, and you do lista.insert(x, lista.pop())
where x is bigger than 8, basically you’re removing the last element (pop) and adding it at the end, so, nothing changes. Hence, you could also change range(len(lista)) to range(len(lista)//2). Test if it’ll work when len(lista) is odd