问题
Please I am a bit new to Python
and it has been nice, I could comment that python is very sexy till I needed to shift content of a 4x4 matrix which I want to use in building a 2048 game demo of the game is here I have this function
def cover_left(matrix):
new=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
for i in range(4):
count=0
for j in range(4):
if mat[i][j]!=0:
new[i][count]=mat[i][j]
count+=1
return new
This is what this function does if you call it like this
cover_left([
[1,0,2,0],
[3,0,4,0],
[5,0,6,0],
[0,7,0,8]
])
It will cover the zeros to the left and produce
[ [1, 2, 0, 0],
[3, 4, 0, 0],
[5, 6, 0, 0],
[7, 8, 0, 0]]
Please I need someone to help me with a numpy
way of doing this which I believe will be faster and require less code (I am using in a depth-first search algo) and more importantly the implementation of cover_up
, cover_down
and
`cover_left`.
`cover_up`
[ [1, 7, 2, 8],
[3, 0, 4, 0],
[5, 0, 6, 0],
[0, 0, 0, 0]]
`cover_down`
[ [0, 0, 0, 0],
[1, 0, 2, 0],
[3, 0, 4, 0],
[5, 7, 6, 8]]
`cover_right`
[ [0, 0, 1, 2],
[0, 0, 3, 4],
[0, 0, 5, 6],
[0, 0, 7, 8]]
Thanks in advance.
回答1:
Here's a vectorized approach inspired by this other post and generalized to cover non-zeros
for all four directions -
def justify(a, invalid_val=0, axis=1, side='left'):
"""
Justifies a 2D array
Parameters
----------
A : ndarray
Input array to be justified
axis : int
Axis along which justification is to be made
side : str
Direction of justification. It could be 'left', 'right', 'up', 'down'
It should be 'left' or 'right' for axis=1 and 'up' or 'down' for axis=0.
"""
if invalid_val is np.nan:
mask = ~np.isnan(a)
else:
mask = a!=invalid_val
justified_mask = np.sort(mask,axis=axis)
if (side=='up') | (side=='left'):
justified_mask = np.flip(justified_mask,axis=axis)
out = np.full(a.shape, invalid_val)
if axis==1:
out[justified_mask] = a[mask]
else:
out.T[justified_mask.T] = a.T[mask.T]
return out
Sample runs -
In [473]: a # input array
Out[473]:
array([[1, 0, 2, 0],
[3, 0, 4, 0],
[5, 0, 6, 0],
[6, 7, 0, 8]])
In [474]: justify(a, axis=0, side='up')
Out[474]:
array([[1, 7, 2, 8],
[3, 0, 4, 0],
[5, 0, 6, 0],
[6, 0, 0, 0]])
In [475]: justify(a, axis=0, side='down')
Out[475]:
array([[1, 0, 0, 0],
[3, 0, 2, 0],
[5, 0, 4, 0],
[6, 7, 6, 8]])
In [476]: justify(a, axis=1, side='left')
Out[476]:
array([[1, 2, 0, 0],
[3, 4, 0, 0],
[5, 6, 0, 0],
[6, 7, 8, 0]])
In [477]: justify(a, axis=1, side='right')
Out[477]:
array([[0, 0, 1, 2],
[0, 0, 3, 4],
[0, 0, 5, 6],
[0, 6, 7, 8]])
回答2:
Thanks to all this is what I later use
def justify(a, direction):
mask = a>0
justified_mask = numpy.sort(mask,0) if direction == 'up' or direction =='down' else numpy.sort(mask, 1)
if direction == 'up':
justified_mask = justified_mask[::-1]
if direction =='left':
justified_mask = justified_mask[:,::-1]
if direction =='right':
justified_mask = justified_mask[::-1, :]
out = numpy.zeros_like(a)
out.T[justified_mask.T] = a.T[mask.T]
return out
来源:https://stackoverflow.com/questions/44558215/python-justifying-numpy-array