Trying to spread out difference between cells in list - python

I have a list that moves around 100 by a small bit (see the list in the code below). For the days that I have 0, I would like to spread out the difference of the previous cells.
(I'm counting zero as the first cell in the text below, because python)
To give an example, the original_list below has the value 100.41191500000001 in cell 2, and 0 in cells 3,4,5. I would like to take the change abs(original_list[1]-original_list[2])=1,26108000000001, and spread it out over the three days. So basically I would like cell 2 to be occupied by original_list[1]+(1.26108000000001/4), cell 3 to be new_list[2] + (1.26108000000001/4), cell 4 to be new_list[3] + (1.26108000000001/4), and finally cell 5 to also be new_list[4] + (1.26108000000001/4).
I divide by four because I want the change that happened between cell 1 and 2, to be spread out evenly between cells 1 to 5.
The code below presents what I've tried, but I'm not sure if this is the best approach. Any help would be greatly appreciated.
original_list = [98.87464, 99.150835, 100.41191500000001, 0, 0, 0, 101.650165, 0, 0, 0, 0, 0, 101.850421, 0, 99.970131, 100.244205, 98.550495, 0, 0, 97.496535, 97.971645]
new_list = [0 for i in range(len(original_list))]
for i in range(len(original_list)):
j = i
if original_list[i] == 0:
while original_list[j] == 0:
j += 1
elif original_list[i] != 0:
new_list[i] = original_list[i]
if j != i:
for k in range(0,j-i+1):
new_list[i+k] = new_list[i-1] + abs(new_list[i]-new_list[i-1])/(j-i+1)
print(new_list)

It's not the best approach as it will not give your expected result.
The for loops iterates over all the elements of the range. You have an inner for loop in the if j != i: block which calculate the replacement values for the following 0's. When the control is returned to the main for loop, it is going to recalculate those values, giving unexpected numbers.
I think your math to calculate new_list[i+k] is wrong. If I understood correctly, it does not reproduce what you describe in your question.
In your case a while loop is recommended. In the case where original_list[i] != 0: you increment the index by 1, in the case where original_list[i] == 0: you need to set the index of the proper value so that it corresponds to the next non null element in your original list, which should be i = j.
And of course you need to fix the math.
I would wrote the code in this way:
new_list = []
i = 0
while i < len(original_list):
if original_list[i] == 0:
j = i+1
while original_list[j] == 0 and j < len(original_list):
j += 1 #searching the index of the next non null value
#please check if the following math is what you really need, fix it in case.
diff = original_list[j] - new_list[-1]
inslist = [new_list[-1] + (k*diff)/(j-i+1) for k in range(1, (j-i+1))]
new_list.extend(inslist)
i = j
elif original_list[i] != 0:
new_list.append(original_list[i])
i += 1
You can compare the two list with: print([(o, n) for o, n in zip(original_list, new_list)]) and see if each original - new pair of values is correct.

Related

How do I obtain the Maximum Number of Jumps?

I was recently asked the following simple question during one of the coding interviews:
You are given an integer array "numbers" and some difference "diff" as your inputs.
You can jump to the next square (or index) as long as these conditions are satisfied:
i != j
numbers[i] == numbers[j]
The absolute difference between indices are less than or equal to "diff", abs(i-j) <= diff.
Find the maximum number of squares in that particular array.
Although, it is unsatisfying in terms of time complexity, I came up with solution below for the sake of time constraints. However, it does not give the correct answer most of the time.
Is there anyone who can point out the flaws in my solution?
Thanks in advance.
def count_jump(numbers, diff):
index_dict = dict()
for i in range(len(numbers)):
if numbers[i] not in index_dict:
index_dict[numbers[i]] = []
index_dict[numbers[i]].append(i)
max_ = 0
for item in index_dict:
result = 0
i = 0
for j in index_dict[item]:
if i != j and numbers[i] == numbers[j] and abs(i-j) <= diff:
i = j
result+=1
max_ = max(max_, result)
return max_+1
a = [1, 2, 1, 3, 3, 1, 1, 2]
print(count_jump(a, 3))
For the example above, the maximum number of squares that we can jump is 4. Start from index 0, jump to index 2, and then to 5, and then to 6.
Apparently, assigning the variable "i" to 0 each and every time was a mistake. Instead, it should be assigned to the first index of the item that we are investigating.
Since we do not have to include each square with the same value, i.e we can discard the first element if it is too far away from other values, the result should be set to 0 after each dissatisfaction of the condition.
max_ = 0
for item in index_dict:
result = 0
i = index_dict[item][0]
for j in index_dict[item]:
if i != j and abs(i-j) <= diff:
result+=1
max_ = max(max_, result)
else:
result = 0
i = j

Fill list of zero numbers under conditions in a nested list

This is a question I met in interview yesterday, so I cannot provide link to the original question here
Here is the description:
I am given an array of integers like this [0,2,3],[1,0,0] where zeros
stand for missing parts that I need to fill with the following
conditions:
I am also given a number k, which means every number $a_{i}$ choose to fill is between 1 and k
After filling the number, the list should be in this order: a1<=a2<=a3...<=an(but I should not change the order of the index, which means I cannot fill in a bunch of numbers and sort the list)
Here is what I have done yesterday:
list1 = []
#%%
k = 3
a = [0,2,3]
for i in range(len(a)):
if a[i] == 0:
for j in range(1,k+1):
a[i] = j
print('a,',a)
print('list1:',list1)
if a[0] > a[1]:
continue
else:
print(a)
rv = 0
for m in range(1,(len(a)-1)):
if a[m] <= a[m+1]:
rv+=1
if rv == len(a) - 2:
print('value',a)
print('before;',list1)
list1.append(a.copy())
print('after',list1)
This can only solve list with one zero number, so anybody could help me solve the problem?
Extra explanation:
If you want a short solution and your only conditions are the fill numbers are between 1 and k and each fill number has to be equal to or greater than the last fill number this will work:
k = 5
a = [0 , 2, 3, 0]
answer = list(map(lambda i: 1 if i==0 else i, a))
This obviously plays on the fact that all the fill numbers can be equal. If you want a more complete and verbose solution with increasing fill numbers you should keep track of the current/last fill number outside of your loop like so:
k = 5
last_fill = 1
a = [0, 1, 2, 0]
for i in range(len(a)):
if a[i] == 0:
if last_fill > k:
print("Value out of k range!")
break
a[i] = last_fill
last_fill += 1
Rereading through your question, I'm a little unsure if you would like the entire list to be sorted at the end or not. That being said, you can use sort to take care of any sorting such as in the above answer = list(map(lambda i: 1 if i==0 else i, a)).sort().

Comparing elements in a list in order using loop or stack/queue

I have a list ls with integer elements between 0 and 100. I want to build a function that counts a number of elements until it encounters an element that has a larger value, and appends the count to the solution list.
In other words, if ls = [5, 10, 1, 1, 20, 1], the solution should be [1, 3, 2]:
1 comes from the first element, 5
3 comes from the second to fourth elements, 10, 1, 1
2 comes from the last two elements, 20, 1
(If ls = [7, 3, 9], the return should be [2,1].)
I used a for loop to perform the task:
def compare_and_count(ls):
answer = []
num = 1
ref = 0
for j in range(1, len(ls)):
try:
if ls[ref + j] <= ls[ref]:
num += 1
else:
answer.append(num)
num = 1
ref = ref + j
except IndexError:
break
answer.append(num)
return answer
I tried to do a value comparison with two movable references, but this raises IndexError and also sometimes neglects the final counting and hence returns an incorrect list. (I added try...except to be free of the IndexError, but the latter problem is still unsolved)
I assume either loop or stack/queue is the most concise way to solve this, but I couldn't land an optimal way yet. Any insight is appreciated.
Edited the answer to correct it .
def my(a):
count = 1
maxval = a[0]
answer = []
for i in range(1, len(a)):
if a[i] > maxval:
maxval = a[i]
answer.append(count)
count = 1
else:
count += 1
answer.append(count)
return answer
I tried to do a value comparison with two movable references
You dont need to, just one moving index i and one count counter with a maxval to check the condition.

Sorting algorithm in Python

Currently I found this code while learning from a video. However, the code has a flaw which was pointed out but I am unable to understand part of the algorithm and why that flaw is a 'flaw'.
i = len(numList) - 1
while i > 1:
j = 0
while j < i:
# If the value on the left is bigger switch values
if numList[j] > numList[j+1]:
temp = numList[j]
numList[j] = numList[j + 1]
numList[j + 1] = temp
else:
print()
j += 1
i -= 1
for k in numList:
print(k, end=", ")
print()
The code is supposed to order numbers from a list of numbers, however I am unable to understand two things out of it:
One is "Why is 1 subtracted from "i"?"
i = len(numList) - 1
And two, when the last number of the algorithm is "1" the algorithm won't order the numbers properly. For example, a list of "4, 2, 6, 3, 1" will be ordered as "2, 1, 3, 4, 6" instead of the correct "1, 2, 3, 4, 6,". People from the comments pointed out the reason for this is that it should be "while i > 0" or "while i >= 1" instead of "while i > 1".
while i > 1:
However I am unable to understand why it is like that.
"Why is 1 substracted from "i"?"
Because collections are zero-indexed. You have N elements, but the last indexable value is always N-1
When j < i and you access numList[j+1], then for when j is at its max value, j == i-1, and i is at its max value of len(numList) - 1, then you access numList[(i-1)+1] == numList[i] == numList[len(numList) - 1], which is the last available element.
two and the one that makes my head hurt the most
while i > 0 is correct because in the first iteration, i == 1 and j == 0, and you swap j+1 == 1 and j == 0 index when numList[j] > numList[j+1], so therefore 2 (index 1) and 1 (index 0) would be flipped, and you get 1,2,3,4,6 from 2,1,3,4,6
The algorithm carries the maximum of the first i+1 numbers to the front (so i+1-th position), by switching the neighbours until the maximum 'bubbles up'.
In the first iteration, i = len(numList) - 1, so the maximum of the whole numList
(index starts at 0 and ends at len(numList) - 1) is carried to the front.
This is the maximum value, which should be last. Now you only have to worry about
the first i - 1 values, therefore i is reduced by one.
Because i > 1 forgets about carrying the first element to the front (being the second position), 2 and 1 in your example are not ordered correctly, as they would need to switch.
Therefore you need the i = 1 iteration step.
There is a great site, which helps with visualisation of the sorting algorithms.
https://visualgo.net/en/sorting?slide=1. Your algorithm is called bubble-sort.

Counting consecutive numbers in all columns of a 2D array

I have a 2d array, X, that looks like this
[0, 0, 0, 2, 1]
[1, 2, 1, 0, 1]
[2, 2, 1, 0, 0]
[0, 0, 1, 2, 0]
I'm trying to iterate through the entire 2D array to try and count all the instances where there are 2 consecutive elements in a column. E.g. X above would return 4 (X[1][1] == X[2][1] && X[1][2] == X[2][2] && X[2][2] == X[3][2] and so on)
I'm finding this very hard to visualize. So far I have:
def get_opposite(number):
if number == 2: return 1
if number == 1: return 2
def counter(X, number):
count = 0
for i in range(len(X)):
for j in range(len(X[i])-1):
if X[i][j] == X[i][j+1] and X[i][j] != 0 and X[i][j] != get_opposite(number):
count += 1
return count
I keep either getting vastly incorrect results, or IndexError, it should be fairly straight forward but I'm not sure what I'm doing wrong
If you compare the example you give in the text with your actual code, you'll notice your code is comparing with the value on the right, not the with the value below it. You need to apply +1 to the first index, not the second. This also means the range of your loops has to be adapted accordingly.
Secondly, you don't need the first function. The equality comparison is enough.
Also, I removed the second argument of the function, as it serves no role:
def counter(X):
count = 0
for i in range(len(X)-1):
for j in range(len(X[i])):
if X[i][j] == X[i+1][j] and X[i][j] != 0:
count += 1
return count

Categories

Resources