Input is a numpy matrix and the procedure is to find all entries above 3 in the matrix. When the program has found an entry with a value of 4 or higher, the program must subtract 4 from that matrix position and distribute that 4 - one to the cell above, one to the cell below, one to the cell to the left and one to the cell to the right.
Input is [ [3,3,3], [3,4,3], [3,3,3] ], and I expect an output of [ [3,4,3], [4,0,4], [3,4,3] ].
Instead I get [ [3,4,4], [4,2,1], [4,1,1] ]
The 4 in the middle of the input matrix needs to be taken out and redistributed to the adjacent cell elements of the matrix; one above, one below, one to the left and one to the right. This does not happen. I cannot make sense of it. Anyone, please.
I added some constraints - so that if an entry in the matrix does have an entry of 4 or larger close to the boundary of the matrix - this will make sure that you add one only to existing entries in the matrix.
import numpy as np
dimension = 3
abba = np.matrix( [ [3,3,3], [3,4,3], [3,3,3] ] )
# implement the rules
def sandpile(field):
for x in range(dimension):
for y in range (dimension):
if field[x,y] > 3:
field[x,y] = field[x,y] - 4
if x 1 < dimension:
field[x 1,y] = field[x 1,y] 1
if x-1 >= 0:
field[x-1,y] = field[x-1,y] 1
if y-1 >= 0:
field[x,y-1] = field[x,y-1] 1
if y 1 < dimension:
field[x,y 1] = field[x,y 1] 1
return (field)
print(abba)
abba = sandpile(abba)
print(abba)
CodePudding user response:
Here is an implementation using np.where
and assuming periodic boundaries. If you want the additions to 'leak' out of the matrix you have to filter out the right, left, top, bottom conditions accordingly.
import numpy as np
dimx, dimy = 3, 3
a = np.random.randint(0, 5, (dimx, dimy))
greater3 = np.where(a > 3)
print(a)
left = (greater3[0], greater3[1]-1)
right = (greater3[0], (greater3[1]-1) % dimy)
top = (greater3[0] - 1, greater3[1])
bottom = ((greater3[1]-1) % dimx, greater3[1])
a[greater3] -= 4
a[left] = 1
a[right] = 1
a[top] = 1
a[bottom] = 1
print(a)