Python numpy 替换特定模式的值

Python numpy replacing values that are in certain pattern

我正在尝试 'avoid walls' 使用 A* 星 (A-Star) 算法。 我的数组如下所示:

[1, 1, 1, 0, 0, 0, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 1, 1, 1],
[1, 0, 0, 0, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 1, 1, 1, 1, 1],
[1, 1, 0, 0, 0, 1, 1, 1, 1],
[1, 1, 1, 0, 0, 0, 1, 1, 1]

我只能在 0(零)和 1(一)上行走。 我希望我的 AI 走在路径的中心,假设有足够的空间可以行走。 AI可以斜走

例如而不是 [1, 1, 1, 0, 0, 0, 1, 1, 1],(第一个数组),因为有足够的空间不阻塞路径我怎么能用 [1, 1, 1, 1, 0, 1, 1, 1, 1],

替换它

事后思考:

The optimal path here if we will walk on center is [4 3 2 2 3 4].

Also, what if we are given the shortest path possible for this case it would be [3 3 3 3 4 4] if we are going from (3, 0) to (4, 5). If we just don't want walls in our path like having a single element before the wall, how can we arrive to [3 3 2 2 3 4] if we allow start and finish to touch walls?

编辑: Ali_Sh 答案是我最初寻找的,也是公认的答案。

这是一个示例,其中它仅查找每行中的所有零值并将路径设置为中间参数。如果一行有两个零补丁,这可能 运行 会遇到麻烦。在这种情况下,您需要确保零​​补丁上方和下方的参数也是零补丁。

我在这里使用了matplotlib来可视化路径:

import matplotlib.pyplot as plt

p = []
A = [[1, 1, 1, 0, 0, 0, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 1, 1, 1],
[1, 0, 0, 0, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 1, 1, 1, 1, 1],
[1, 1, 0, 0, 0, 1, 1, 1, 1],
[1, 1, 1, 0, 0, 0, 1, 1, 1]]

for i in range(len(A)):
    ptemp = []
    for j in range(len(A[0])):
        if A[i][j] == 0:
            ptemp.append(j) # find all the zero values
    p.append(ptemp[int(len(ptemp)/2)]) # set the path as the center zero value
    
print(p)
plt.imshow(A[::-1])
plt.plot(p[::-1],range(len(A)))
plt.show()

如果a为主数组,每行中间0的索引可以通过:

cond = np.where(a == 0)
unique = np.unique(cond[0], return_index=True, return_counts=True)
ind = unique[1] + unique[2] // 2
cols = cond[1][ind]  # --> [4 3 2 2 3 4]

它可用于用主数组形状替换 ones 数组中的 1 值:

one = np.ones(shape=a.shape)
one[np.arange(len(one)), cols] = 0

这将:

[[1. 1. 1. 1. 0. 1. 1. 1. 1.]
 [1. 1. 1. 0. 1. 1. 1. 1. 1.]
 [1. 1. 0. 1. 1. 1. 1. 1. 1.]
 [1. 1. 0. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 0. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 0. 1. 1. 1. 1.]]

对于问题的更新部分,如果我们有另一个列路径而不是 中指定的最佳路径(例如 [3 1 1 1 2 3] 而不是 [4 3 2 2 3 4]),它可以是仅应用:

cols = np.array([3, 1, 1, 1, 2, 3])
one = np.ones(shape=a.shape)
one[np.arange(len(one)), cols] = 0

# [[1. 1. 1. 0. 1. 1. 1. 1. 1.]
#  [1. 0. 1. 1. 1. 1. 1. 1. 1.]
#  [1. 0. 1. 1. 1. 1. 1. 1. 1.]
#  [1. 0. 1. 1. 1. 1. 1. 1. 1.]
#  [1. 1. 0. 1. 1. 1. 1. 1. 1.]
#  [1. 1. 1. 0. 1. 1. 1. 1. 1.]]

如果我们想要除边界之外的所有路径,我们可以在前面的答案代码中添加以下代码:

if we don't fully walk on the center but just avoid 'near walls' path just even 1 offset from the walls:

cols_min = cols - (unique[2] - 2) // 2
cols_max = cols + (unique[2] - 2) // 2
one[np.arange(len(one)), cols_min] = 0
one[np.arange(len(one)), cols_max] = 0

# [[1. 1. 1. 1. 0. 1. 1. 1. 1.]
#  [1. 1. 0. 0. 0. 1. 1. 1. 1.]
#  [1. 1. 0. 1. 1. 1. 1. 1. 1.]
#  [1. 1. 0. 1. 1. 1. 1. 1. 1.]
#  [1. 1. 1. 0. 1. 1. 1. 1. 1.]
#  [1. 1. 1. 1. 0. 1. 1. 1. 1.]]

当我们可以触摸第一行和最后一行的墙壁(这里是其中一个)时,我们可以在前面的答案代码中添加以下代码:

col_min_first = cols[0] - unique[2][0] // 2
col_min_last = cols[-1] - unique[2][-1] // 2
one[0, col_min_first:cols[0]] = 0
one[-1, col_min_last:cols[-1]] = 0

# [[1. 1. 1. 0. 0. 1. 1. 1. 1.]
#  [1. 1. 1. 0. 1. 1. 1. 1. 1.]
#  [1. 1. 0. 1. 1. 1. 1. 1. 1.]
#  [1. 1. 0. 1. 1. 1. 1. 1. 1.]
#  [1. 1. 1. 0. 1. 1. 1. 1. 1.]
#  [1. 1. 1. 0. 0. 1. 1. 1. 1.]]

最后,如果我们想找到最短路径,我们可以通过找到其中最大数量0的列来实现目标,首先,然后找到最近的列索引0 到该列,因为该列不包含 0:

ind_max = np.argmax(np.sum(a == 0, axis=0))
mask_rows = a[:, ind_max] != 0
mask_col_min = a[:, ind_max - 1] == 0
mask_col_max = a[:, ind_max + 1] == 0
ind_max = np.where(mask_rows & mask_col_min, ind_max - 1, ind_max)
ind_max = np.where(mask_rows & mask_col_max, ind_max + 1, ind_max)
one = np.ones(shape=a.shape)
one[np.arange(len(one)), ind_max] = 0

# [[1. 1. 1. 0. 1. 1. 1. 1. 1.]   | a = np.array([[1, 1, 1, 0, 0, 0, 1, 1, 1],        [[1. 1. 1. 0. 1. 1. 1. 1. 1.]
#  [1. 1. 1. 0. 1. 1. 1. 1. 1.]   |               [1, 0, 0, 0, 0, 0, 1, 1, 1],         [1. 1. 1. 0. 1. 1. 1. 1. 1.]
#  [1. 1. 1. 0. 1. 1. 1. 1. 1.]   |               [0, 0, 0, 1, 1, 1, 1, 1, 1],   -->   [1. 1. 0. 1. 1. 1. 1. 1. 1.]
#  [1. 1. 1. 0. 1. 1. 1. 1. 1.]   |               [1, 0, 0, 0, 1, 1, 1, 1, 1],         [1. 1. 1. 0. 1. 1. 1. 1. 1.] 
#  [1. 1. 1. 0. 1. 1. 1. 1. 1.]   |               [1, 1, 0, 0, 0, 1, 1, 1, 1],         [1. 1. 1. 0. 1. 1. 1. 1. 1.]
#  [1. 1. 1. 0. 1. 1. 1. 1. 1.]]  |               [1, 1, 1, 0, 0, 0, 1, 1, 1]])        [1. 1. 1. 0. 1. 1. 1. 1. 1.]]