Найти индексы элементов во всех «восьми направлениях» 2D-массива / матрицы Python

#python #python-3.x #matrix #multidimensional-array #lambda

#питон #python-3.x #матрица #многомерный массив #лямбда — выражение

Вопрос:

Как я могу найти индексы ВСЕХ элементов во всех восьми направлениях (влево, вправо, вверх, вниз, влево-вверх, вправо-вверх, влево-вниз, влево-вниз, вправо-вниз) данной 2D-матрицы / массива?

Например, в приведенной ниже матрице я ищу, чтобы извлечь элементы, помеченные X для ввода 0 и так далее…:

 X**X**X
*X*X*X*
**XXX**
XXX0XXX
**XXX**
 
 X0XXXXX
XXX****
*X*X***
*X**X**
*X***X*
 

Я использовал эту лямбда-функцию, чтобы получить список всех смежных элементов во всех восьми направлениях.

 X = len(grid)
Y = len(grid[0])
neighbors = lambda x, y : [(x2, y2) for x2 in range(x-1, x 2)
                               for y2 in range(y-1, y 2)
                               if (-1 < x < X and
                                   -1 < y < Y and
                                   (x != x2 or y != y2) and
                                   (0 <= x2 < X) and
                                   (0 <= y2 < Y))]

**XXX**
**X0X**
**XXX**
*******
 

Я хочу иметь возможность расширить вышесказанное, чтобы получить вышесказанное.

Комментарии:

1. Каков ожидаемый результат для двух матриц? для первого, должно ли оно иметь восемь пар индексов (т.Е. Индексы соседних «X» s?)

Ответ №1:

Ниже приведены индексы по всем восьми направлениям:

 from itertools import product

def valid_indexes(lst, row, col):
    return row in range(len(lst)) and col in range(len(lst[0]))

# Queen's view since it's the same as what a queen in chess can 'view'
def queens_view(lst, row, col, dr=0, dc=0):
    if dr or dc:
        yield (row, col)
        if valid_indexes(lst, row dr, col dc):
            yield from queens_view(lst, row dr, col dc, dr, dc)
    else:
        for dr, dc in product([-1, 0, 1], [-1, 0, 1]):
            if dr or dc and valid_indexes(lst, row dr, col dc):
                yield from queens_view(lst, row dr, col dc, dr, dc)

start_row, start_col = 3, 4 # Index of the '0' in your list
for row, col in queens_view(lst, start_row, start_col):
    print(row, col)
    # Do what you like with the index
 

Ответ №2:

Вы можете создать функцию, которая «стреляет» во всех направлениях от нужной точки до достижения конца сетки. Возвращает все найденные точки:

 def direction_points(g_len_x, g_len_y, point_x, point_y):

    result = []

    directions = [
        [0, -1],    # up
        [1, -1],    # up right
        [1, 0],     # right
        [1, 1],     # down right
        [0, 1],     # down
        [-1, 1],    # down left
        [-1, 0],    # left
        [-1, -1],   # left up
        ]

    for direction in directions:

        x = point_x
        y = point_y
        end_reached = False
        while not end_reached:

            x = x   direction[0]
            y = y   direction[1]
            if (0 <= x < g_len_x) and not end_reached:
                if (0 <= y < g_len_y) and not end_reached:
                    result.append([x, y])
                else:
                    end_reached = True
            else:
                end_reached = True

    return result
 

С помощью этого вы можете создавать линии или сетку:

 grid_len_x = 10
grid_len_y = 12
mid_point_x = 4
mid_point_y = 6

points = direction_points(grid_len_x, grid_len_y, mid_point_x, mid_point_y)

lines = []
for y in range(grid_len_y):
    line = ''
    for x in range(grid_len_x):

        if [x, y] in points:
            line  = 'X'
        else:
            if x == mid_point_x and y == mid_point_y:
                line  = '0'
            else:
                line  = '*'
    lines.append(line)

for line in lines:
    print(line)
 

Результат

 ****X*****
****X****X
X***X***X*
*X**X**X**
**X*X*X***
***XXX****
XXXX0XXXXX
***XXX****
**X*X*X***
*X**X**X**
X***X***X*
****X****X