Selecting a list slice, reversing it, and updating the list - python

I'm trying to get some guidance on how to implement this algorithm in python. I'm currently trying to solve adventofcode.com/2017/day/10.
I understand the logic of what needs to be done, but where I'm stuck is implementing this in code specifically taking a selection/slice of a list, reversing it, then "putting it back" into said list.
The example they give is:
Suppose we instead only had a circular list containing five elements, [0, 1, 2, 3, 4] and were given input lengths of [3, 4, 1, 5].
The list begins as [0] 1 2 3 4 (where square brackets indicate the current position).
The first length, 3, selects [0] 1 2) 3 4 (where parentheses indicate the sublist to be reversed).
After reversing that section (0 1 2 into 2 1 0), we get ([2] 1 0) 3 4.
Then, the current position moves forward by the length, 3, plus the skip size, 0: 2 1 0 [3] 4. Finally, the skip size increases to 1.
The second length, 4, selects a section which wraps: 2 1) 0 ([3] 4.
The sublist 3 4 2 1 is reversed to form 1 2 4 3: 4 3) 0 ([1] 2.
The current position moves forward by the length plus the skip size, a total of 5, causing it not to move because it wraps around: 4 3 0 [1] 2. The skip size increases to 2.
I know I will use a for loop for each length, then based on the current "cursor" position, create a slice that starts at the cursor position, and contains the amount of elements that matches the current iteration (in the second example it would be 4). I feel like this needs to be solved using the %, list slicing, and the length of the list but can't figure it out. Any guidance or help would be much appreciated even if it's resources to learn how to solve this versus just the answer. But I'll take anything. Thanks friends.

Related

Python find index of last element smaller than number

I have a list of numbers from 0 to 3 and I want to remove every number that is smaller than 2 xor is not connected to the last 3 in the list. It is also going to be done about 200 Million times so it should preferably perform well. For example, I could have a list like that:
listIwantToCheck = [3, 0, 1, 2, 0, 2, 3, 2, 2, 3, 2, 0, 2, 1]
listIWantToGet = [2, 3, 2, 2, 3]
I already have the index of the last 3 so what I would do is:
listIWantToGet = listIWantToCheck[??? : indexOfLastThree + 1]
??? being 4 in this instance. It is the index with the mentioned conditions.
So How do I get the index of the last number smaller than 2?
Nailed it, the index i want is
index = ([0]+[i for i, e in enumerate(listIWantToCheck[:indexOfLastThree]) if e < 2])[-1] + 1
List comprehension is truly beautiful.
I enumerated through the slice and created a list of all indices, which point to a number smaller than 2 and took the last. The 0 in front is added to circumvent an index error, which would occur if there are no elements smaller than 2.
So if i get this right you want to get the index of the last number smaller than 2 that comes before the last 3.
My approach would be to take the part of the list from index 0 to the index of the last 3 and then reverse the list and check if the number is smaller than 2.
If you however want to get the last 2 of the entire list just reverse it and loop through it the same way
for i in listIWanttoCheck[0:indexOfLastThree].reverse():
if i <2:
return listIWanttoCheck.index(i)
Correct me if I missunderstood your problem

How do I derive this part of the algorithm

I'm a beginner at programming Python and came across this program.
This algorithm is used to reverse a list:
mylist = [1,2,3,4]
reverse = mylist[:]
for i in range(len(reverse)//2):
reverse[i], reverse[len(reverse) -i -1] = reverse[len(reverse) -i -1], reverse[i]
This algorithm is based on the logic that the swapping process will happen only till the len/2 element for lists with even lengths or the len/2 element in case of lists with a odd length because if the swapping process occurred till the last element, the list would remain the same as it was in the beginning.
I understood what the below part does, but how do I derive it, please explain the logic:
reverse[len(reverse) -i -1]
len(reverse) returns the number of elements the list has. To actually use it as an index you need to subtract 1 from it as indices start from 0. Next, we also subtract i from it as we are moving i positions away from both ends of the list and swapping them.
So if i=1 reverse[i] points to 2 while reverse[len(reverse)-i-1 points to 3.
You can just print the contents of these variables:
lst = [1, 2, 3, 4, 5, 6]
for i in range(len(lst)//2):
print(i, len(lst) - i - 1)
This will print
0 5
1 4
2 3
Therefore,
for the index of the first element (i = 0), len(lst) - i - 1 will return the index of the last element (i = 5).
for the index of the second element (i = 1), len(lst) - i - 1 will return the index of the second to last element (i = 4).
And so on.

How to randomly select from a list over iterations yet choose every member of the list at least once?

I would like my code to iterate four times (or possibly larger) over a list with a length of 3 while visiting every number on the list at least once.
for i in range(4):
rand_selection = random.choice([1, 0, -1])
print(rand_selection)
In the above code, it will have a chance of not selecting every single item on the list.
For example, it might not print -1 even once if it randomly happened to choose 1 1 0 1.
Thank you for your advice and help.
This solution feels like a scam but,
import random
lis = [1, 0, -1]
random.shuffle(lis)
print(lis+[random.choice(lis)])
Returns a list of 4 numbers which can be designated as your 4 choices.

Trying to solve an array related question of avoiding obstacles from codesignal

I've been trying to solve this stage in codesignal wherein the function has to return how many steps to avoid the obstacles starting from 0, and the size of the jump has to remain constant all throughout the array. e.g [5,3,6,7,9] should give an output of 4, as it starts from 0, lands at 4, jumps again, and lands at 8, and by jumping 4 places, it avoids every element in the given array.
I've looked at the solutions to try and understand how to solve this more efficiently and I came across this solution in particular
def avoidObstacles(inputArray):
c = 2
while True:
if sorted([i%c for i in inputArray])[0]>0:
return c
c += 1
I understood everything in the solution except for 1 part: \
what exactly does the [0] after the sorted array do in this code? \
if sorted([i%c for i in inputArray])[0] > 0
sorted returns a list with the elements sorted. Here the code means If the first element of the sorted list is greater than 0

why the swapping does not take place when indices are 0 and 1?

I have an unordered array consisting of consecutive integers [1, 2, 3, ..., n] without any duplicates. It is allowed to swap any two elements. I need to find the minimum number of swaps required to sort the array in ascending order.
Starting from the first element of the list, I try to put them in their right position (for example if the first element is 7 it should be in the 6th position of the list). To go one by one in the list, I make a copy, and do the swapping in the second list.
a = [4,3,1,2]
b = a[:]
swap = 0
for p in a:
if (p!= b[p-1]):
b[p-1], b[b.index(p)] = b[b.index(p)], b[p-1]
swap+=1
print(swap)
this code works, except for the case that I have to swap two elements in the list whose position is either 0 or 1, in this case . which I don't understand why?? since I'm not exceeding the limit.
Can anyone please explain to me why this happens?
For example, if I print p, two indices where swapping happens, updated list of b and updated number of swaps:
p = 4
idx1= 3 idx2= 0
b= [2, 3, 1, 4]
swap = 1
p = 3
idx1= 2 idx2= 1
b= [2, 1, 3, 4]
swap = 2
p = 1
idx1= 0 idx2= 1
b= [2, 1, 3, 4]
swap = 3
p = 2
idx1= 1 idx2= 0
b= [1, 2, 3, 4]
swap = 4
In this case, you can see that for p = 1, when indices are 0 and 1, the swapping is not taking place.
I changed the order of b[p-1], b[b.index(p)] and I don't have the same problem anymore, but I don't understand the reason.
I have encountered the same problem before, and stucked for a while. The reason to cause this is the order of multiple assignment.
b[p-1], b[b.index(p)] = b[b.index(p)], b[p-1]
Actually multiple assignment is not exactly assign at the same time. pack and unpack mechanism behind this. so it will change b[p-1] first, and b.index(p) in b[b.index(p)] will be find a new index which is p-1 when the case p=1 idx1=0 idx2=1
if you change the assignment order, it will work fine.
b[b.index(p)], b[p - 1] = b[p - 1], b[b.index(p)]
or calculate idx first:
idx1, idx2 = p - 1, b.index(p)
b[idx1], b[idx2] = b[idx2], b[idx1]
I recommend the second version, because first version will do index twice. cost twice time than second version.
you can refer to my related question here: The mechanism behind mutiple assignment in Python
by the way, I think your algorithm is inefficient here, to decrease swap time, but use O(n) index operation, and also copy a array here. I think you can use the same idea, just swap in orignal array.

Categories

Resources