Suppose we have a matrix that is filled with three letters 'O', 'G', and 'W' where 'O' is representing open space, 'G' is representing guards and 'W' is representing walls in a bank, we have to replace all of the O's in the matrix with respect of their shortest distance from one guard, we cannot go through any walls. In the output matrix guards are replaced with 0 and walls are replaced by -1.
So, if the input is like
O | O | O | O | G |
O | O | O | W | O |
O | W | O | O | O |
G | W | W | W | O |
O | O | O | O | G |
then the output will be
3 | 3 | 2 | 1 | 0 |
2 | 3 | 3 | -1 | 1 |
1 | -1 | 4 | 3 | 2 |
0 | -1 | -1 | -1 | 1 |
1 | 2 | 2 | 1 | 0 |
To solve this, we will follow these steps −
M := 5
N := 5
dir_row := [-1, 0, 1, 0]
dir_col := [0, 1, 0, -1]
Define a function is_ok() . This will take i, j
if (i in range 0 and M) or (j in range 0 and j N), then
return False
return True
Define a function isSafe() . This will take i, j,matrix, result
if matrix[i, j] is not 'O' or result[i, j] is not -1, then
return False
return True
Define a function calculate_dist() .This will take matrix
result := make a matrix of order M x N and fill with -1
Define a double ended queue q
for i in range 0 to M, do
for j in range 0 to N, do
result[i, j] := -1
if matrix[i, j] is same as 'G', then
pos := [i, j, 0]
insert pos at the left of q
result[i, j] := 0
while size of q > 0 is non-zero, do
curr := delete last element from q
x, y, dist := curr[0], curr[1], curr[2]
for i in range 0 to 3, do
if is_ok(x + dir_row[i], y + dir_col[i]) is non-zero and isSafe(x + dir_row[i], y + dir_col[i], matrix, result) is non-zero, then
result[x + dir_row[i], y + dir_col[i]] := dist + 1
pos := [x + dir_row[i], y + dir_col[i], dist + 1]
insert pos at the left of q
for i in range 0 to M, do
for j in range 0 to N, do
display result[i, j]
go to next line
Example
Let us see the following implementation to get better understanding −
from collections import deque as queue M = 5 N = 5 dir_row = [-1, 0, 1, 0] dir_col = [0, 1, 0, -1] def is_ok(i, j): if ((i < 0 or i > M - 1) or (j < 0 or j > N - 1)): return False return True def isSafe(i, j,matrix, result): if (matrix[i][j] != 'O' or result[i][j] != -1): return False return True def calculate_dist(matrix): result = [[ -1 for i in range(N)]for i in range(M)] q = queue() for i in range(M): for j in range(N): result[i][j] = -1 if (matrix[i][j] == 'G'): pos = [i, j, 0] q.appendleft(pos) result[i][j] = 0 while (len(q) > 0): curr = q.pop() x, y, dist = curr[0], curr[1], curr[2] for i in range(4): if is_ok(x + dir_row[i], y + dir_col[i]) and isSafe(x + dir_row[i], y + dir_col[i], matrix, result) : result[x + dir_row[i]][y + dir_col[i]] = dist + 1 pos = [x + dir_row[i], y + dir_col[i], dist + 1] q.appendleft(pos) for i in range(M): for j in range(N): if result[i][j] > 0: print(result[i][j], end=" ") else: print(result[i][j],end=" ") print() matrix = [['O', 'O', 'O', 'O', 'G'], ['O', 'O', 'O', 'W', 'O'], ['O', 'W', 'O', 'O', 'O'], ['G', 'W', 'W', 'W', 'O'], ['O', 'O', 'O', 'O', 'G']] calculate_dist(matrix)
Input
[['O', 'O', 'O', 'O', 'G'], ['O', 'O', 'O', 'W', 'O'], ['O', 'W', 'O', 'O', 'O'], ['G', 'W', 'W', 'W', 'O'], ['O', 'O', 'O', 'O', 'G']]
Output
3 3 2 1 0 2 3 3 -1 1 1 -1 4 3 2 0 -1 -1 -1 1 1 2 2 1 0