How to access the adjacent cells of each elements of matrix in python?

Question:

Here two cells are considered adjacent if they share a boundary.
For example :

A = 5 6 4
    2 1 3
    7 9 8

Here adjacent elements to index 0,0 is at index [0,1] and [1,0] and for index 1,1 the adjacent elements are at index [0,1],[1,0],[2,1] and [1,2].

Asked By: Anonymous

||

Answers:

Supposed you have mxn matrix, and you want to find the adjacent indices of the cell (i, j):

def get_adjacent_indices(i, j, m, n):
   adjacent_indices = []
    if i > 0:
        adjacent_indices.append((i-1,j))
    if i+1 < m:
        adjacent_indices.append((i+1,j))
    if j > 0:
        adjacent_indices.append((i,j-1))
    if j+1 < n:
        adjacent_indices.append((i,j+1))
    return adjacent_indices
Answered By: Lior

To also check for diagonals, regarding what Casper Dijkstrao asked, I usually write some code like this:

def adj_finder(matrix, position):
    adj = []
    
    for dx in range(-1, 2):
        for dy in range(-1, 2):
            rangeX = range(0, matrix.shape[0])  # X bounds
            rangeY = range(0, matrix.shape[1])  # Y bounds
            
            (newX, newY) = (position[0]+dx, position[1]+dy)  # adjacent cell
            
            if (newX in rangeX) and (newY in rangeY) and (dx, dy) != (0, 0):
                adj.append((newX, newY))
    
    return adj

The function gets the matrix argument to extract the size of its row and column (I use numpy, so matrix.shape returns (row_size, column_size) tuple).

It also gets the current cell as pointer argument (it’s like (X,Y)).

Then It generate adjacent cells, and if they were legit (1. they were not out of the bound, and 2. not identical to reference position), it adds them to adjacent list, adj.

I’d like to emphasize that using the above algorithm, you can easily obtain neighbors in farther distances as well. Just modify the range in the for loops, like this:

for v in range(0-distance, 1+distance):
    for h in range(0-distance, 1+distance):
        ...

Where distance is the maximum distance of adjacent you want to let in.

Answered By: Amir Maleki

This will be another way – prob. involve some math tricks or regarded more concise (if you’re more math-inclined) :

def neighbours(grid, r, c):
    vals = sum((row[c -(c>0): c+2]
                for row in grid[r -(r>0):r+2]), [])
    vals.remove(grid[r][c])     # rm itself.
    return vals       


grid = [[1, 5, 4, 9], 
        [2, 8, 3, 8], 
        [6, 3, 6, 3], 
        [7, 4, 7, 1]]

Outputs: (all items are in order)

print(f' {neighbours(grid, 2, 2)} ') # [8, 3, 8, 3, 3, 4, 7, 1] 
print(f' {neighbours(grid, 0, 0)} ') # [5, 2, 8] 
print(f' {neighbours(grid, 1, 1)} ') # [[1, 5, 4, 2, 3, 6, 3, 6] 
Answered By: Daniel Hao