Find Shortest Distance from a Guard in a Bank in Python



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
Updated on: 2020-08-19T11:19:35+05:30

147 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements