考虑以下N×N矩阵 A 和 B 只包含正整数:
[i,j]
位置。 [i,j]
。例如:
[3, 2]
位置,有4
个奇数[3, 1, 5, 3]
邻居A[3,2]
。 12
,
存储在B[3,2]
此代码通过蛮力工作,分别对9个区域中的每个区域进行操作(即:顶部,底部,左侧,右侧,4个角和内部)。
有没有更好的方法来解决这个问题?
from numpy import array,zeros,shape
def sum_neighbours(A):
A = array(A,int)
r,c = shape(A)
B = zeros(shape(A),int)
for i in range(r):
for j in range(c):
N_list_i = [0,-1,-1,-1,0,1,1,1,0] #[l,tl,t,tr,r,br,b,bl]
N_list_j = [-1,-1,0,1,1,1,0,-1,-1]
# innerSquares
if 1 <= i <= (r-2) and 1 <= j <= (r-2):
for k in range(len(N_list_j)-1):
if A[i+N_list_i[k]][j+N_list_j[k]] %2 != 0:
B[i][j] += A[i+N_list_i[k]][j+N_list_j[k]]
#TopLeft
elif i==0 and j==0:
N_list_i = N_list_i[4:(4+3)]
N_list_j = N_list_j[4:(4+3)]
for k in range(len(N_list_j)):
if A[i+N_list_i[k]][j+N_list_j[k]] %2 != 0:
B[i][j] += A[i+N_list_i[k]][j+N_list_j[k]]
#BottomLeft
elif j==0 and i==(r-1):
N_list_i = N_list_i[2:(2+3)]
N_list_j = N_list_j[2:(2+3)]
for k in range(len(N_list_j)):
if A[i+N_list_i[k]][j+N_list_j[k]] %2 != 0:
B[i][j] += A[i+N_list_i[k]][j+N_list_j[k]]
#TopRight
elif i==0 and j == (r-1):
N_list_i = N_list_i[6:(6+3)]
N_list_j = N_list_j[6:(6+3)]
for k in range(len(N_list_j)):
if A[i+N_list_i[k]][j+N_list_j[k]] %2 != 0:
B[i][j] += A[i+N_list_i[k]][j+N_list_j[k]]
#BottomRight
elif i == (r-1) and j == (r-1):
N_list_i = N_list_i[0:(0+3)]
N_list_j = N_list_j[0:(0+3)]
for k in range(len(N_list_j)):
if A[i+N_list_i[k]][j+N_list_j[k]] %2 != 0:
B[i][j] += A[i+N_list_i[k]][j+N_list_j[k]]
#TopBorder
elif i==0 and j < (r-1):
N_list_i = N_list_i[4:(4+5)]
N_list_j = N_list_j[4:(4+5)]
for k in range(len(N_list_j)):
if A[i+N_list_i[k]][j+N_list_j[k]] %2 != 0:
B[i][j] += A[i+N_list_i[k]][j+N_list_j[k]]
#LeftBorder
elif j==0 and i < (r-1):
N_list_i = N_list_i[2:(2+5)]
N_list_j = N_list_j[2:(2+5)]
for k in range(len(N_list_j)):
if A[i+N_list_i[k]][j+N_list_j[k]] %2 != 0:
B[i][j] += A[i+N_list_i[k]][j+N_list_j[k]]
#BottomBorder
elif i==(r-1) and j < (r-1):
N_list_i = N_list_i[0:(0+5)]
N_list_j = N_list_j[0:(0+5)]
for k in range(len(N_list_j)):
if A[i+N_list_i[k]][j+N_list_j[k]] %2 != 0:
B[i][j] += A[i+N_list_i[k]][j+N_list_j[k]]
#RightBorder
elif j==(r-1) and i < (r-1):
N_list_i = [1,1,0,-1,-1]
N_list_j = [0,-1,-1,-1,0]
for k in range(len(N_list_j)):
if A[i+N_list_i[k]][j+N_list_j[k]] %2 != 0:
B[i][j] += A[i+N_list_i[k]][j+N_list_j[k]]
return B
A = array([[3,2,8,1,1],
[1,2,4,1,1],
[7,3,4,1,8],
[1,8,0,6,4],
[5,6,5,3,8]])
答案 0 :(得分:1)
在重构方面,你几乎肯定想要避免&#34;蛮力&#34;在必须明确键入所有案例的意义上:) @alexmcf解决了上述问题。
在概念上,您的方法直接遵循问题陈述:检查矩阵中每个数字的所有邻居并将所有奇数相加。这意味着您总是在进行检查和求和,即使矩阵中没有奇数。
作为替代方案:我们可以首先浏览矩阵并识别奇数。然后,从空矩阵开始,我们只需将奇数加到所有有效邻居。这节省了与矩阵中奇数的稀缺成比例的工作。
import numpy as np
def find_offsets(row, col, size):
"""Return all valid pairs of offsets as [(row_offset, col_offset)...]."""
offsets = ((-1, -1), (-1, 0), (-1, 1),
(0, -1), (0, 1),
(1, -1), (1, 0), (1, 1))
return [(r_off, c_off) for r_off, c_off in offsets
if row + r_off >= 0 and row + r_off < size
if col + c_off >= 0 and col + c_off < size]
def find_odds(matrix, size):
"""Return all odd values in matrix as [(row_ind, col_ind, value)...]."""
return [(row, col, matrix[row][col])
for row in xrange(size)
for col in xrange(size)
if matrix[row][col] % 2 != 0]
def gen_matrix(source, size):
"""Filter source 2x2 matrix for odds and add each to valid neighbors."""
out = np.zeros((size, size), dtype=int)
# filter for location and value of all odd numbers
odds = find_odds(source, size)
for row, col, value in odds:
# add odd number to all valid neighbors (by finding valid offsets)
offsets = find_offsets(row, col, size)
for r_off, c_off in offsets:
out[row + r_off][col + c_off] += value
return out
def sum_neighbors():
"""Sum neighbors as described in problem."""
N = 5
A = [[3,2,8,1,1],
[1,2,4,1,1],
[7,3,4,1,8],
[1,8,0,6,4],
[5,6,5,3,8]]
return gen_matrix(A, N)
以上运行速度大约是代码的两倍(对于苹果与苹果的比较,我在iPython中执行时调整了上述内容,以便在两种情况下都提供相同的矩阵A作为参数):
In [19]: %timeit original.sum_neighbours(A)
1000 loops, best of 3: 195 µs per loop
In [20]: %timeit new.sum_neighbors(A)
10000 loops, best of 3: 84 µs per loop
答案 1 :(得分:0)
import numpy as np
def sum_neighbours_NEW(A):
A = np.array(A,int)
r,c = np.shape(A)
B = np.zeros(A.shape, int)
def b(x,y, size=A.shape):
xlim,ylim = size # get limits of axes
# generate a list of all i,j bordering x,y
# this will cause the most slowdown... for faster code, you minimise
# the number of tims idx gets called by making it a parameter of b()
# adding x and y and doing a np.where() to ensure it doesn't
# index out of the array range
idx = [[x+i,y+j] for i in range(-1,2) for j in range(-1,2) \
if (i,j) != (0,0) and (x+i>=0 and y+j>=0) and (x+i<xlim and y+j<ylim)]
idx = np.asarray(idx) # convert to numpy array
return idx[:,0], idx[:,1] # split into x,y for indexing
# iterate across all elements of A
for i in xrange(r):
for j in xrange(c):
els = A[b(i,j)]
sum_A = els[np.where(els % 2)].sum() # only sum odd elements
B[i,j] = sum_A
return B
A = array([[3,2,8,1,1],
[1,2,4,1,1],
[7,3,4,1,8],
[1,8,0,6,4],
[5,6,5,3,8]])
# check new function vs. old function
(sum_neighbours(A) == sum_neighbours_NEW(A)).all()
True
尝试使用此循环扫描“周围元素”,它会返回x,y
元素的元组,这些元素分为numpy indexing <指定的单个x
和y
数组/ p>
def b(x,y, size=A.shape):
xlim,ylim = size # get limits of axes
# generate a list of all i,j bordering x,y
idx = [[x+i,y+j] for i in range(-1,2) for j in range(-1,2) \
if (i,j) != (0,0) and (x+i>=0 and y+j>=0) and (x+i<xlim and y+j<ylim)]
idx = np.asarray(idx) # convert to numpy array
return idx[:,0], idx[:,1] # split into x,y for indexing
idx = b(3,2)
# check correct by matching indexes e.g.
# (idx[0][0],idx[1][0]) => (2,1) , (idx[0][1],idx[1][1]) => (2,2) etc.
print idx
(array([2, 2, 2, 3, 3, 4, 4, 4]), array([1, 2, 3, 1, 3, 1, 2, 3]))
然后您可以通过以下方式访问 A 中的元素
els = A[idx]
print els
array([3, 4, 1, 8, 6, 6, 5, 3])
然后你可以通过以下方式对所有奇数元素求和:
print els[np.where(els % 2)].sum()
12
使用此方法获取 A 中每个元素的总和。
答案 2 :(得分:0)
这部分应该有助于获得奇怪的元素。
import numpy as np
# generate an array of random integers
A = np.random.random_integers(1,10, [20,10])
# get only the odd values back from the array
A_odds = A*(A%2!=0)
# pad the array with zeros to make summing easier
A_odds_padded = np.pad(array=A_odds, pad_width=1, mode='constant')
# iterate elements and sum
B = np.zeros(np.shape(A))
for i in range(shape(B)[0]):
for j in range(shape(B)[1]):
#etc
答案 3 :(得分:-2)
我有这个:
def find_odd_sum(arr):
# Pad the original array
arr_pad = np.pad(arr, 1, 'constant', constant_values=0)
shape = np.shape(arr)
arr_b = np.zeros((shape[0] + 2, shape[1] + 2))
for ii in range(0, shape[0]): #rows
for jj in range(0, shape[1]): #cols
point = np.array([ii+1, jj+1])
# Points to check
kernel = [np.array([-1, 0]),
np.array([0, 1]),
np.array([1, 0]),
np.array([0, -1]),
np.array([-1, -1]),
np.array([1, 1]),
np.array([-1, 1]),
np.array([1, -1])]
points = [k+point for k in kernel]
s = [arr_pad[points[i][0], points[i][1]] for i in range(len(points))]
s1 =sum([i for i in s if i % 2 != 0])
arr_b[point[0], point[1]] = s1
return arr_b[1:-1, 1:-1]
>>>
[[ 1. 4. 2. 3. 3.]
[ 13. 14. 6. 4. 4.]
[ 5. 9. 5. 2. 3.]
[ 15. 21. 12. 9. 4.]
[ 1. 11. 3. 5. 3.]]