Группировка координат нулевых значений в массиве 2D numpy в списки на основе их положения в матрице - PullRequest
1 голос
/ 24 февраля 2020

За исключением значений нулевых границ, можно ли сгруппировать координаты (в виде кортежей) оставшихся нулевых значений в разные списки в этом массиве numpy?

[[ 0  0  0  0  0  0  0  0  0  0  0]
 [ 0  1  1  1  0  0  0  1 10  2  0]
 [ 0  2 10  2  1  0  0  1  2 10  0]
 [ 0 10  3 10  1  0  0  0  1  1  0]
 [ 0  1  2  1  1  0  0  0  0  0  0]
 [ 0  1  2  1  2  2  2  1  0  0  0]
 [ 0 10  2 10  2 10 10  1  0  0  0]
 [ 0  1  2  1  2  2  2  1  1  1  0]
 [ 0  0  0  0  0  0  0  0  1 10  0]
 [ 0  0  0  0  0  0  0  0  1  1  0]
 [ 0  0  0  0  0  0  0  0  0  0  0]]

для примера. в приведенной выше сетке есть две «группы» нулей, одна в левом нижнем углу и другая в верхнем правом углу. можно ли их поместить в отдельные списки для каждой сгенерированной матрицы? Ниже приведен код для создания матрицы 'sol_mat': -

import numpy as np
import random

bomb_mat = np.zeros((11,11), dtype = int)
for i in range(10):
    a = random.randint(1,9)
    b = random.randint(1,9)
    bomb_mat[a,b] = 1

sol_mat = np.zeros(11,11), dtype = int)
for j in range(1,10):
    for k in range(1,y-1):
        if bomb_mat[j,k] == 1:
            sol_mat[j,k] = 10
        else:
            sol_mat[j,k] = bomb_mat[j-1,k-1] + bomb_mat[j,k-1] + bomb_mat[j+1,k-1]+ bomb_mat[j-1,k] + bomb_mat[j+1,k] + bomb_mat[j-1,k+1] + bomb_mat[j,k+1] + bomb_mat[j+1,k+1]

Попытка создать тральщик

1 Ответ

1 голос
/ 24 февраля 2020

Я внес некоторые коррективы в ваш код. Главным образом я пытался избежать циклов и использовал scipys convolve2d() для создания sol_mat. Основным преимуществом этого метода является то, что вам не нужно беспокоиться о крайних случаях изображения. Использование 3x3 kernel из ones для логического массива бомб дает точное количество соседних бомб (флаги в тральщике).

import numpy as np
from scipy.signal import convolve2d

grid_size = (7, 7)
n_bombs = 5

bomb_mat = np.zeros(grid_size, dtype=int)
bomb_mat[np.random.randint(low=1, high=grid_size[0]-1, size=n_bombs),
         np.random.randint(low=1, high=grid_size[1]-1, size=n_bombs)] = 1
# array([[0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 1, 0, 0],
#        [0, 0, 1, 0, 0, 0, 0],
#        [0, 1, 1, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 1, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0]])

sol_mat = convolve2d(bomb_mat, np.ones((3, 3)), mode='same').astype(int)
sol_mat[bomb_mat.astype(bool)] = 10
# array([[ 0,  0,  0,  1,  1,  1,  0],
#        [ 0,  1,  1,  2, 10,  1,  0],
#        [ 1,  3, 10,  3,  1,  1,  0],
#        [ 1, 10, 10,  2,  0,  0,  0],
#        [ 1,  3,  3,  2,  0,  0,  0],
#        [ 0,  1, 10,  1,  0,  0,  0],
#        [ 0,  1,  1,  1,  0,  0,  0]])

Вы можете использовать np.tril() и np.triu(), чтобы получить нижний и верхний треугольник массива. Построив пересечение булевых треугольников с условием sol_mat == 0, вы получите искомые индексы:

lower0 = np.logical_and(np.tril(np.ones(grid_size)), sol_mat == 0)
# lower0.astype(int)
# array([[1, 0, 0, 0, 0, 0, 0],
#        [1, 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, 1, 1, 0],
#        [1, 0, 0, 0, 1, 1, 1]])
upper0 = np.logical_and(np.triu(np.ones(grid_size)), sol_mat == 0)
# upper0.astype(int)
# array([[1, 1, 1, 0, 0, 0, 1],
#        [0, 0, 0, 0, 0, 0, 1],
#        [0, 0, 0, 0, 0, 0, 1],
#        [0, 0, 0, 0, 1, 1, 1],
#        [0, 0, 0, 0, 1, 1, 1],
#        [0, 0, 0, 0, 0, 1, 1],
#        [0, 0, 0, 0, 0, 0, 1]])

Вы можете получить индексы этих массивов через np.nonzero():

lower0_idx = np.array(np.nonzero(lower0))
# array([[0, 1, 4, 5, 5, 5, 6, 6, 6, 6],
#        [0, 0, 4, 0, 4, 5, 0, 4, 5, 6]])
upper0_idx = np.array(np.nonzero(upper0))
# array([[0, 0, 0, 0, 1, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6],
#        [0, 1, 2, 6, 6, 6, 4, 5, 6, 4, 5, 6, 5, 6, 6]])
...