Reversing a list within a list - python

I wrote the function below and it works if the len(list_of_list) is even. I'm having trouble when it's odd. When I run it, it ends up with an Assertion Error. How do I reverse only the elements in the first and last list index and not the ones in between when the list of lists is odd?
def flip_diag(list_of_list):
for i in range(int(len(list_of_list) % 2 != 0)):
list_of_list[0][::-1] = reversed(list_of_list[0][::-1])
list_of_list[-1][::-1] = reversed(list_of_list[-1][::-1])
for i in range(int(len(list_of_list) % 2 == 0)):
reversed_list = [elem[::-1] for elem in list_of_list]
return reversed_list
if __name__ == '__main__':
assert flip_diag([[1, 0, 0, 0], [0, 2, 0, 0], [0, 0, 3, 0], [0, 0, 0, 4]]) == [[0, 0, 0, 1],[0, 0, 2, 0], [0, 3, 0, 0], [4, 0, 0, 0]]
assert flip_diag([[0, 0, 0], [0, 1, 0], [0, 0, 1]]) == [[0, 0, 0], [0, 1, 0], [1, 0, 0]]
assert flip_diag([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) == [[0, 0, 1], [0, 1, 0], [1, 0, 0]]
assert flip_diag([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) == [[3, 2, 1], [4, 5, 6], [9, 8, 7]]

one way to do it via list comprehension:
def flip_diag(list_of_list):
if len(list_of_list) % 2 != 0:
return [item[::-1] if index in [0, len(list_of_list)-1] else item for index, item in enumerate(list_of_list)]
return [item[::-1] for index, item in enumerate(list_of_list)]

If the length of list_of_list is odd, you can have the below for loop in place to only reverse the first and last index elements each list inside list_of_list:
>> list_of_list = [[1, 0, 0, 0], [0, 2, 0, 0], [0, 0, 3, 0]]
>> for i in range(int(len(list_of_list) % 2 != 0)):
>> reversed_list = [elem[-1:-2:-1]+elem[1:-1]+elem[0:1] for elem in list_of_list]
>> print(reversed_list)
[[0, 0, 0, 1], [0, 2, 0, 0], [0, 0, 3, 0]]
If you want to use map and lambda you can do it like below:
>> list_of_list = [[1, 0, 0, 0], [0, 2, 0, 0], [0, 0, 3, 0]]
>> for i in range(int(len(list_of_list) % 2 != 0)):
>> reversed_list = list(map(lambda elem: elem[-1:-2:-1]+elem[1:-1]+elem[0:1] ,list_of_list))
>> print(reversed_list)
[[0, 0, 0, 1], [0, 2, 0, 0], [0, 0, 3, 0]]

Related

Getting a list of 3 by 3 boxes in a Sudoku puzzle

Assuming the sudoku puzzle is a 9 by 9 and is filled with 0-9. I want is 9 lists, with each list containing a 3 by 3 Sudoku box.
This is what I have:
grid = [[5, 0, 0, 0, 0, 0, 0, 0, 1],
[0, 1, 0, 0, 8, 7, 0, 6, 0],
[0, 0, 0, 0, 0, 3, 0, 0, 0],
[0, 5, 0, 0, 6, 1, 0, 7, 0],
[0, 0, 2, 0, 0, 0, 9, 0, 0],
[0, 0, 0, 4, 0, 0, 0, 0, 0],
[0, 0, 0, 5, 0, 0, 0, 4, 0],
[9, 0, 0, 0, 4, 8, 7, 0, 0],
[0, 8, 0, 3, 0, 0, 0, 0, 0]]
list1 = []
for i in range(0,3):
for j in range(0,3):
list1.append(grid[i][j])
list2 = []
for i in range(0,3):
for j in range(4,7):
list2.append(grid[i][j])
and it goes on and on.......
How do I simplify this for loop for getting a list of 3 by 3 boxes in Sudoku puzzle?
You need to add a step parameter to your range()s so that you start reading in each box at the appropriate row / column index:
from itertools import product
boxes = []
for row_start, col_start in product(range(0, 9, 3), repeat=2):
boxes.append([
[grid[row][col] for col in range(col_start, col_start + 3)]
for row in range(row_start, row_start + 3)
])
print(boxes)
This outputs:
[
[[5, 0, 0], [0, 1, 0], [0, 0, 0]],
[[0, 0, 0], [0, 8, 7], [0, 0, 3]],
[[0, 0, 1], [0, 6, 0], [0, 0, 0]],
[[0, 5, 0], [0, 0, 2], [0, 0, 0]],
[[0, 6, 1], [0, 0, 0], [4, 0, 0]],
[[0, 7, 0], [9, 0, 0], [0, 0, 0]],
[[0, 0, 0], [9, 0, 0], [0, 8, 0]],
[[5, 0, 0], [0, 4, 8], [3, 0, 0]],
[[0, 4, 0], [7, 0, 0], [0, 0, 0]]
]
from pprint import pprint as pp
SIZE = 3
sudoku = [[[0] * SIZE for _ in range(SIZE)] for _ in range(SIZE * SIZE)]
# example of populating it
for i in range(SIZE):
for j in range(SIZE):
counter = i * SIZE + j
sudoku[counter][i][j] = counter + 1
pp(sudoku)
output
[[[1, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 2, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 3], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [4, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 5, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 6], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [7, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 8, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 9]]]

Zero-out array elements with matching indices

I'd like to "zero-out" all elements of an n-dimensional array that are in positions with two or more matching indices. In two dimensions, this is effectively np.fill_diagonal() but that function becomes inadequate when a third dimension is considered.
Below is the brute-force version of what I'd like to do. Is there any way to clean this up and make it work in n dimensions?
x = np.ones([3,3,3])
x[:,0,0] = 0
x[0,:,0] = 0
x[0,0,:] = 0
x[:,1,1] = 0
x[1,:,1] = 0
x[1,1,:] = 0
x[:,2,2] = 0
x[2,:,2] = 0
x[2,2,:] = 0
print(x)
One way is np.einsum:
>>> a = np.ones((4,4,4), int)
>>> for n in range(3):
... np.einsum(f"{'iijii'[n:n+3]}->ij", a)[...] = 0
...
>>> a
array([[[0, 0, 0, 0],
[0, 0, 1, 1],
[0, 1, 0, 1],
[0, 1, 1, 0]],
[[0, 0, 1, 1],
[0, 0, 0, 0],
[1, 0, 0, 1],
[1, 0, 1, 0]],
[[0, 1, 0, 1],
[1, 0, 0, 1],
[0, 0, 0, 0],
[1, 1, 0, 0]],
[[0, 1, 1, 0],
[1, 0, 1, 0],
[1, 1, 0, 0],
[0, 0, 0, 0]]])
General (ND) case:
>>> from string import ascii_lowercase
>>> from itertools import combinations
>>>
>>> a = np.ones((4,4,4,4), int)
>>> n = a.ndim
>>> ltrs = ascii_lowercase[:n-2]
>>> for I in combinations(range(n), 2):
... li = iter(ltrs)
... np.einsum(''.join('z' if k in I else next(li) for k in range(n)) + '->z' + ltrs, a)[...] = 0
...
>>> a
array([[[[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]],
[[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 1],
[0, 0, 1, 0]],
[[0, 0, 0, 0],
[0, 0, 0, 1],
[0, 0, 0, 0],
[0, 1, 0, 0]],
<snip>

Python - Shift/Delete Elements in a 2-Dimensional Array

I need help with shifting and deleting elements in a 2-dimensional array.
If the value in a list is negative and their is a list above it with positive values in the same location. It should shift everything down, causing the negative values to disappear.
If there isn't any list above it or the corresponding values in the list above are just 0. It will replace the negative values with 0.
Note: The positive values should never disappear, they can only move down when needed. Only the negative values (below -100) disappear.
These examples should explain it better:
Scenario 1:
DATA: [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 2, 1, 0, 0], [2, 1, 2, 0, 0], [-103, -103, -103, 0, 0]]
EXPECT: [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 2, 1, 0, 0], [2, 1, 2, 0, 0]]
Scenario 2:
DATA: [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 2, -101, -101, -101], [0, 1, 2, 3, 2], [0, 3, 3, 2, 3]]
EXPECT: [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 2, 0, 0, 0], [0, 1, 2, 3, 2], [0, 3, 3, 2, 3]]
Scenario 3: (This is the only one that I got working in my code below.)
DATA: [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 3, 1, 0, 0], [-102, -102, -102, 0, 0], [3, 1, 3, 0, 0]]
EXPECT: [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 3, 1, 0, 0], [3, 1, 3, 0, 0]]
def move(data):
c_count = 4
while c_count >= 0:
count = len(data) - 1
prev = count - 1
while count > 0 and prev >= 0:
if data[count][c_count] < -100:
while prev >= 0 and data[prev][c_count] == 0:
prev -= 1
data[count][c_count] = data[prev][c_count]
data[prev][c_count]= 0
count -= 1
prev -= 1
c_count -= 1
return data
my_data = [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 3, 1, 0, 0], [-102, -102, -102, 0, 0], [3, 1, 3, 0, 0]]
x = move(my_data) # This is (scenario 3) is the only one that works.
print(x)
Thanks so much for your help! I have been stuck on this for a while.
I work with columns separately, not with full rows.
search in column from bottom to top
find negative value
find positive value (bigger then zero) above
if not found then put zero in place of negative
if found then move down all value above
move above to row, above-1 to row-1, above-2 to row-2, etc.
BTW: it is easier to search solution when rows are displayed one below another.
def move(data):
# work in column, not with full rows
for col in range(len(data)):
# move from bottom to top
for row in range(len(data[0])-1, -1, -1):
# check if negative value
if data[row][col] < 0:
print('debug: negative:', data[row][col])
# find positive value above
above = row-1
while above > -1 and data[above][col] <= 0:
above -= 1
# check if found positive value
if above == -1:
# put zero if not found value above
print('debug: put zero')
data[row][col] = 0
else:
# move down all values above
print('debug: move down', above+1, 'element(s)')
while above > -1:
data[row][col] = data[above][col]
data[above][col] = 0
row -= 1
above -= 1
return data
# --- function to run one scenario, display data and check result ---
def run(data, expect):
print('data:')
print('\n'.join(str(row) for row in data))
print()
result = move(data)
print()
print('result:')
print(result)
print('expect:')
print(expect)
print('expect == result:', expect == result)
print('---')
# --- scenarios ---
def scenario1():
DATA = [
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[1, 2, 1, 0, 0],
[2, 1, 2, 0, 0],
[-103, -103, -103, 0, 0]
]
EXPECT = [
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[1, 2, 1, 0, 0],
[2, 1, 2, 0, 0]
]
run(DATA, EXPECT)
def scenario2():
DATA = [
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 2, -101, -101, -101],
[0, 1, 2, 3, 2],
[0, 3, 3, 2, 3]
]
EXPECT = [
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 2, 0, 0, 0],
[0, 1, 2, 3, 2],
[0, 3, 3, 2, 3]
]
run(DATA, EXPECT)
def scenario3(): #(This is the only one that I got working in my code below.)
DATA = [
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[1, 3, 1, 0, 0],
[-102, -102, -102, 0, 0],
[3, 1, 3, 0, 0]
]
EXPECT = [
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[1, 3, 1, 0, 0],
[3, 1, 3, 0, 0]
]
run(DATA, EXPECT)
# --- start scenarios ---
scenario1()
scenario2()
scenario3()
Results:
data:
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[1, 2, 1, 0, 0]
[2, 1, 2, 0, 0]
[-103, -103, -103, 0, 0]
debug: negative: -103
debug: move down 4 element(s)
debug: negative: -103
debug: move down 4 element(s)
debug: negative: -103
debug: move down 4 element(s)
result:
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 2, 1, 0, 0], [2, 1, 2, 0, 0]]
expect:
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 2, 1, 0, 0], [2, 1, 2, 0, 0]]
expect == result: True
---
data:
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 2, -101, -101, -101]
[0, 1, 2, 3, 2]
[0, 3, 3, 2, 3]
debug: negative: -101
debug: put zero
debug: negative: -101
debug: put zero
debug: negative: -101
debug: put zero
result:
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 2, 0, 0, 0], [0, 1, 2, 3, 2], [0, 3, 3, 2, 3]]
expect:
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 2, 0, 0, 0], [0, 1, 2, 3, 2], [0, 3, 3, 2, 3]]
expect == result: True
---
data:
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[1, 3, 1, 0, 0]
[-102, -102, -102, 0, 0]
[3, 1, 3, 0, 0]
debug: negative: -102
debug: move down 3 element(s)
debug: negative: -102
debug: move down 3 element(s)
debug: negative: -102
debug: move down 3 element(s)
result:
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 3, 1, 0, 0], [3, 1, 3, 0, 0]]
expect:
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 3, 1, 0, 0], [3, 1, 3, 0, 0]]
expect == result: True
---
Here's a simple numpy approach i.e
import numpy as np
def get_arr(arr):
arr = np.array(arr)
arr[arr<1] = 0
new_arr = arr[np.argsort(arr.sum(1)),:]
return new_arr.tolist()
arr = [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 2, 1, 0, 0], [2, 1, 2, 0, 0], [-103, -103, -103, 0, 0]]
arr1 = [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 2, -101, -101, -101], [0, 1, 2, 3, 2], [0, 3, 3, 2, 3]]
arr2 = [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 3, 1, 0, 0], [-102, -102, -102, 0, 0], [3, 1, 3, 0, 0]]
print(get_arr(arr))
print(get_arr(arr1))
print(get_arr(arr2))
#[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 2, 1, 0, 0], [2, 1, 2, 0, 0]]
#[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 2, 0, 0, 0], [0, 1, 2, 3, 2], [0, 3, 3, 2, 3]]
#[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 3, 1, 0, 0], [3, 1, 3, 0, 0]]

Python - Move Elements to the End of a 2-Dimensional Array?

Given this 2D Array - [[0, 0, -1], [1, 0, -2], [2, 0, -3], [3, 0, 0]]
How can I code something in Python that moves everything to the end? (If the end is empty).
So I get something like this - [[0, 0, 0], [1, 0, -1], [2, 0, -2], [3, 0, -3]]
I tried something like this:
count = 0
while count < row: # row is 4 in this case.
if my_array[row-1][2] == 0:
tp = my_array[count][2]
my_array[count][2] = 0
my_array[count+1][2] = tp
else:
break
count += 1
return my_array
But this is what I get instead:
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, -1]]
Update:
Thanks #furas, I spent hours trying to figure this out
How can I also handle a gap in the middle? So if I get something like this:
data = [[0, 0, -1], [0, 0, 0], [0, 0, -3], [0, 0, -4]]
expected = [[0, 0, 0], [0, 0, -1], [0, 0, -3], [0, 0, -4]]
rows = len(data)
if data[-1][-1] == 0:
count = rows-1
while count > 0:
data[count][-1] = data[count-1][-1]
count -= 1
data[0][-1] = 0
print(data)
print(expected)
print(data == expected) # False
Thanks
UPDATE Nov.29 -
I have certain scenarios like these that don't work? Can you help?
DATA: [[0, 0, 0, 0], [1, 2, 1, 0], [2, 1, 2, 0], [0, 0, 0, 0]]
EXPECT: [[0, 0, 0, 0], [0, 0, 0, 0], [1, 2, 1, 0], [2, 1, 2, 0]]
Or if it's negative:
DATA: [[0, 0, 0, 0], [-101, -101, -101, 0], [2, 3, 2, 0], [3, 2, 3, 0]]
EXPECT: [[0, 0, 0, 0], [0, 0, 0, 0], [2, 3, 2, 0], [3, 2, 3, 0]]
Thanks A lot!!
I got something like this
def move(data):
row = len(data)-1
prev = row-1
while row > 0 and prev >= 0:
if data[row][-1] == 0:
while prev >= 0 and data[prev][-1] == 0:
prev -= 1
data[row][-1] = data[prev][-1]
data[prev][-1] = 0
row -= 1
prev -= 1
return data
# --- test ---
examples = [
{
'data': [[0, 0, -1], [0, 0, 0], [0, 0, -3], [0, 0, -4]],
'expected': [[0, 0, 0], [0, 0, -1], [0, 0, -3], [0, 0, -4]],
},
{
'data': [[0, 0, -1], [1, 0, -2], [2, 0, -3], [3, 0, 0]],
'expected': [[0, 0, 0], [1, 0, -1], [2, 0, -2], [3, 0, -3]],
},
]
for ex in examples:
print(ex['data'])
result = move(ex['data'])
print(ex['expected'])
print(result == ex['expected']) # True
I use rows = len(data) and [-1] so it can have any size.
External while check if place row is empty and start internal while which is looking for not-empty elements prev before row. After that it move non-empty element from prev to row and put zero in prev. And it starts again with next row place.
It looks more complicated then other solutions.
Here's a reasonably efficient way to do this. We grab the last column of the grid into a list named lastcol, and then sort lastcol with a key function that tests if each item is not equal to zero. That will move all the zeros to the start of lastcol without disturbing the order of the other elements. And then we copy lastcol back to the grid.
I've modified your test data slightly so that we can see that the code handles gaps and positive & negative values correctly.
grid = [[0, 0, -1], [1, 0, 2], [2, 0, 0], [3, 0, -3], [4, 0, 0]]
print(grid)
lastcol = [u[-1] for u in grid]
lastcol.sort(key=(0).__ne__)
for row, u in zip(grid, lastcol):
row[-1] = u
print(grid)
output
[[0, 0, -1], [1, 0, 2], [2, 0, 0], [3, 0, -3], [4, 0, 0]]
[[0, 0, 0], [1, 0, 0], [2, 0, -1], [3, 0, 2], [4, 0, -3]]
Assuming I'm understanding the goal correctly -- that you'd want a column [0, 1, 0, 2, 3] to become [0, 0, 1, 2, 3] -- then with the use of a helper function to transpose the array, all we need to do is sort the columns using bool as the key function, because non-zero numbers are false, and False < True.
def transpose(seq):
return [list(part) for part in zip(*seq)]
def push(seq):
return transpose(sorted(part, key=bool) for part in transpose(seq))
which gives me
In [29]: push([[0, 0, -1], [1, 0, -2], [2, 0, -3], [3, 0, 0]])
Out[29]: [[0, 0, 0], [1, 0, -1], [2, 0, -2], [3, 0, -3]]
In [30]: push([[0, 0, -1], [0, 0, 0], [0, 0, -3], [0, 0, -4]])
Out[30]: [[0, 0, 0], [0, 0, -1], [0, 0, -3], [0, 0, -4]]

Python - Move Elements in a 2-Dimensional Array?

Given this 2D Array -
[[0, 0, -1], [0, 0, -2], [0, 0, 0], [0, 0, 3], [0, 0, 0]]
How can I code something in Python that shifts once to the end each time it's called? However, it has to stop if it reaches a positive value.
So I get something like this
[[0, 0, 0], [0, 0, -1], [0, 0, -2], [0, 0, 3], [0, 0, 0]]
This is what I have. It works for condition 1 but it does not work for condition 2. What can I tweak so condition 2 also works?
# Condition 1 - Works
data = [[0, 0, -1], [0, 0, -2], [0, 0, -3], [0, 0, 0], [0, 0, 0]]
expected = [[0, 0, 0], [0, 0, -1], [0, 0, -2], [0, 0, -3], [0, 0, 0]] # My Results.
# Condition 2 - Does Not Work
data = [[0, 0, -1], [0, 0, -2], [0, 0, 0], [0, 0, 3], [0, 0, 0]]
expected = [[0, 0, 0], [0, 0, -1], [0, 0, -2], [0, 0, 3], [0, 0, 0]] # This is what I want to get. (But it doesn't work)
rows = len(data)
if data[-1][-1] == 0:
count = rows-1
while count > 0:
data[count][-1] = data[count-1][-1]
count -= 1
data[0][-1] = 0
print(data)
print(expected)
This is what I am getting currently. I want to get the expected for Condition 2 listed in the code snipped above.:
Condition 2 Result:
[[0, 0, 0], [0, 0, -1], [0, 0, -2], [0, 0, 0], [0, 0, 3]]
Thanks
Update #Furas:
Something like this to find the positive value location?
possitive_value = []
for i in range(len(data)):
if data[i][-1] > 0:
possitive_value.append(i, -1)
I think you have to find first positive value and use its position as rows
EDIT: I changed name count to last to make it more readable
# --- function ---
def move(data):
rows = len(data)
# - find positive -
for x in range(rows):
if data[x][-1] > 0:
rows = x # use its position as `rows`
break # don't seach other positiove values
# - star moving -
# set "last" checked row
last = rows-1
# check "last" row
if data[last][-1] == 0:
# move previous values
while last > 0:
data[last][-1] = data[last-1][-1]
last -= 1
# put 0 in first place
data[0][-1] = 0
# --- tests ---
examples = [
{
# Condition 1 - Works
'data': [[0, 0, -1], [0, 0, -2], [0, 0, -3], [0, 0, 0], [0, 0, 0]],
'expected': [[0, 0, 0], [0, 0, -1], [0, 0, -2], [0, 0, -3], [0, 0, 0]], # My Results.
},
{
# Condition 2 - Works
'data': [[0, 0, -1], [0, 0, -2], [0, 0, 0], [0, 0, 3], [0, 0, 0]],
'expected': [[0, 0, 0], [0, 0, -1], [0, 0, -2], [0, 0, 3], [0, 0, 0]], # This is what I want to get. (But it doesn't work)
}
]
for example in examples:
data = example['data']
expected = example['expected']
print(' before:', data)
move(data)
print(' after:', data)
print('expected:', expected)
print(' correct:', data == expected)
print('---')
Result:
before: [[0, 0, -1], [0, 0, -2], [0, 0, -3], [0, 0, 0], [0, 0, 0]]
after: [[0, 0, 0], [0, 0, -1], [0, 0, -2], [0, 0, -3], [0, 0, 0]]
expected: [[0, 0, 0], [0, 0, -1], [0, 0, -2], [0, 0, -3], [0, 0, 0]]
correct: True
---
before: [[0, 0, -1], [0, 0, -2], [0, 0, 0], [0, 0, 3], [0, 0, 0]]
after: [[0, 0, 0], [0, 0, -1], [0, 0, -2], [0, 0, 3], [0, 0, 0]]
expected: [[0, 0, 0], [0, 0, -1], [0, 0, -2], [0, 0, 3], [0, 0, 0]]
correct: True
---
EDIT:
BTW: instead of while you can use for with reversed range() if it makes it more readable
def move(data):
rows = len(data)
# - find positive -
for x in range(rows):
if data[x][-1] > 0:
rows = x # use its position as `rows`
break # don't seach other positiove values
# - star moving -
# set "last" checked row
last = rows-1
# check "last" row
if data[last][-1] == 0:
# move previous values
for pos in range(last, 0, -1): # range with reversed order
data[pos][-1] = data[pos-1][-1]
# put 0 in first place
data[0][-1] = 0
BTW: both versions move items in original data ("in-place") so they don't need return data.
Here's a variation, a function that can be called and will shift data by one every time. I wasn't entirely clear from your question if this was the behavior you wanted.
import numpy as np
def shift_data(data):
ele_idx = [i for i,x in enumerate(data) if x != [0,0,0]]
zero_idx = [i for i,x in enumerate(data) if x == [0,0,0] and i != 0]
if max(np.diff(ele_idx)) == 1 or max(np.diff([i for i,x in enumerate(data) if x == [0,0,0]])) == 1:#things are consecutive
data.insert(0,data.pop(-1))
else:
tt = [l for l in data[ele_idx[0]:zero_idx[0]+1]]
tt.insert(0,tt.pop(-1))
data = data[:ele_idx[0]] + tt + data[zero_idx[0]+1:]
return data
data = [[0, 0, -1], [0, 0, 0], [0, 0, -2], [0, 0, 0], [0, 0, 3]]
print(data)
for _ in range(0,6):
data = shift_data(data)
print(data)
This code outputs:
[[0, 0, -1], [0, 0, 0], [0, 0, -2], [0, 0, 0], [0, 0, 3]]
[[0, 0, 0], [0, 0, -1], [0, 0, -2], [0, 0, 0], [0, 0, 3]]
[[0, 0, 0], [0, 0, 0], [0, 0, -1], [0, 0, -2], [0, 0, 3]]
[[0, 0, 3], [0, 0, 0], [0, 0, 0], [0, 0, -1], [0, 0, -2]]
[[0, 0, -2], [0, 0, 3], [0, 0, 0], [0, 0, 0], [0, 0, -1]]
[[0, 0, -1], [0, 0, -2], [0, 0, 3], [0, 0, 0], [0, 0, 0]]
[[0, 0, 0], [0, 0, -1], [0, 0, -2], [0, 0, 3], [0, 0, 0]]

Categories

Resources