Program to check if number of compass usage to get out of a maze is enough in Python


Suppose, we are playing a game where we are trapped in a maze. We have to find our way out of the maze. The maze can be presented as an x m matrix, where n is the number of rows and m is the number of columns. Each cell/element of the matrix contains any of the symbols 'O','D', 'S', or '-'. 'O' means that the path is blocked, 'D' is the way out from the maze, 'S' is our starting position, and '-' means we can move through the path. We can move freely through any of the '-' marked cells. Now, we also have a compass using which we can find the exit path ('D' cell) from the maze. When we have to find a direction, we have to use the compass. But, we can use the compass at most k times. Given the maze as a matrix and the number of times we can use the compass; we have to find out if we can get out of the maze having used the compass that many times only. If it is possible we return True, or else we return False.

So, if the input is like grid =

-O-O------O
-OD-O-OOO-O
-OO-O-OOO-O
-OO-O-OS---
------OOOO-

n = 4, m = 11, k = 3; then the output will be True.

To solve this, we will follow these steps −

  • Define a function path_search() . This will take curr_pos, grid, total_rows, total_cols, k, predecessor

    • x:= x value of curr_pos

    • y:= y value of curr_pos

    • if grid[x, y] is same as "*", then

      • if k is same as 0, then

        • return True

      • otherwise,

        • return False

      • otherwise,

        • parent := predecessor[curr_pos]

        • succ_pos := a new list from the return values of succesor_positions(curr_pos, grid, total_rows, total_cols, parent)

        • use_compass := True if size of succ_pos > 1

        • for each position in succ_pos, do

          • predecessor[position] := curr_pos

          • if use_compass is non-zero, then

            • path_search(position, grid, total_rows, total_cols, k - 1, predecessor)

          • otherwise,
            • path_search(position, grid, total_rows, total_cols,k, predecessor)

  • Define a function succesor_positions() . This will take curr_pos, grid, total_rows, total_cols, parent

    • x:= x value of curr_pos

    • y:= y value of curr_pos

    • succ_pos := a new list

    • o if y > 0, then

      • left := x, y - 1

      • insert left at the end of succ_pos

    • if y < total_cols - 1, then

      • right := x, y + 1

      • insert right at the end of succ_pos

    • if x > 0, then

      • up := x - 1, y

      • insert up at the end of succ_pos

    • if x < total_rows - 1, then

      • down := x + 1, y

      • insert down at the end of succ_pos

    • if for every position in succ_pos, grid[position[0], pos[1]] is

    • not same as "X" and pos is not same as parent, then −

      • return the elements in succ_pos satisfying the condition

Now perform the following −

  • curr_pos := a new empty pair

  • for each index i, item row in grid, do

    • for each index j, item element in row, do

      • if element is same as 'M', then

        • curr_pos := a new pair containing i, j

  • predecessor := a new map where the curr_pos := Null initially

  • path_search(curr_pos, grid, n, m, k, predecessor)

Source Code (Python)

Let us see the following implementation to get better understanding −

 Live Demo

def path_search(curr_pos, grid, total_rows, total_cols, k, predecessor):
   x, y = curr_pos
   if grid[x][y] == "D":
      if k == 0:
         print('True')
      else:
         print('False')
   else:
      parent = predecessor[curr_pos]
      succ_pos = list(succesor_positions(curr_pos, grid, total_rows, total_cols, parent))
      use_compass = len(succ_pos) > 1
      for position in succ_pos:
         predecessor[position] = curr_pos
         if use_compass:
            path_search(position, grid, total_rows, total_cols, k - 1, predecessor)
         else:
            path_search(position, grid, total_rows, total_cols, k, predecessor)

def succesor_positions(curr_pos, grid, total_rows, total_cols, pred):
   x, y = curr_pos
   succ_pos = []
   if y > 0:
      left = (x, y - 1)
      succ_pos.append(left)
   if y < total_cols - 1:
      right = (x, y + 1)
      succ_pos.append(right)
   if x > 0:
      up = (x - 1, y)
      succ_pos.append(up)
   if x < total_rows - 1:
      down = (x + 1, y)
      succ_pos.append(down)
   return filter(lambda pos: grid[pos[0]][pos[1]] != "O" and pos != pred, succ_pos)

def solve(grid, n, m, k):
   curr_pos = ()
   for i, row in enumerate(grid):
      for j, element in enumerate(row):
         if element == 'S':
            curr_pos = (i, j)
   path_search(curr_pos, grid, n, m, k, predecessor = {curr_pos: None})

grid = [['-', 'O', '-', 'O', '-', '-', '-', '-', '-', '-', 'O'],
['-', 'O', 'D', '-', 'O', '-', 'O', 'O', 'O', '-', 'O'],
['-', 'O', 'O', '-', 'O', '-', 'O', 'S', '-', '-', '-'],
['-', '-', '-', '-', '-', '-', 'O', 'O', 'O', 'O', '-']]

solve(grid, 4, 11, 3)

Input

grid = [['-', 'O', '-', 'O', '-', '-', '-', '-', '-', '-', 'O'],
['-', 'O', 'D', '-', 'O', '-', 'O', 'O', 'O', '-', 'O'],
['-', 'O', 'O', '-', 'O', '-', 'O', 'S', '-', '-', '-'],
['-', '-', '-', '-', '-', '-', 'O', 'O', 'O', 'O', '-']] , 4, 11, 3

Output

True

Updated on: 30-Aug-2021

56 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements