Word Search in Maze using Depth First Search (with python code and step by step code execution walkthrough)
1. Introduction
In this blog, we will explain how to solve the word search problem in a maze using Depth First Search (DFS) algorithm. We will use a 3x3 maze and search for the word 'the' in the maze. The word 'the' is located in the second row of the maze.
2. Algorithm Explanation
The DFS algorithm is used to explore all possible paths in the maze to find the target word. We start from each cell in the maze and recursively explore its neighbors to find the word.
2.1 Steps of the Algorithm
- Start from each cell in the maze.
- Check if the current cell matches the current character of the word.
- Mark the current cell as visited.
- Recursively explore the neighboring cells (up, down, left, right).
- Unmark the current cell and backtrack if the word is not found.
- Return true if the word is found, otherwise return false.
3. Python Code
def dfs(maze, word, i, j, index):
if index == len(word):
return True
if i < 0 or i >= len(maze) or j < 0 or j >= len(maze[0]) or maze[i][j] != word[index]:
return False
temp = maze[i][j]
maze[i][j] = '#'
found = (dfs(maze, word, i+1, j, index+1) or
dfs(maze, word, i-1, j, index+1) or
dfs(maze, word, i, j+1, index+1) or
dfs(maze, word, i, j-1, index+1))
maze[i][j] = temp
return found
def word_search(maze, word):
for i in range(len(maze)):
for j in range(len(maze[0])):
if dfs(maze, word, i, j, 0):
return True
return False
maze = [
['t', 'a', 'b'],
['t', 'h', 'e'],
['o', 'f', 'g']
]
word = "the"
print(word_search(maze, word))
4. Example Maze
The example maze is a 3x3 grid with the word 'the' located in the second row:
t | a | b |
t | h | e |
o | f | g |
Step-by-Step Walkthrough
Initial State
- Maze: [['t', 'a', 'b'], ['t', 'h', 'e'], ['o', 'f', 'g']]
- Word: 'the'
- Starting Point: (0, 0)
Iteration 1: word_search(maze, 'the')
Calls dfs(maze, 'the', 0, 0, 0)
- Current Cell: (0, 0)
- Current Character in Maze: 't'
- Current Character in Word: 't'
- Index: 0
- Mark (0, 0) as visited
- Explores neighbors: (1, 0), (-1, 0), (0, 1), (0, -1)
Iteration 2: dfs(maze, 'the', 1, 0, 1)
Calls dfs(maze, 'the', 1, 0, 1)
- Current Cell: (1, 0)
- Current Character in Maze: 't'
- Current Character in Word: 'h'
- Index: 1
- Characters do not match: Backtracks and return False
Iteration 3: dfs(maze, 'the', 0, 1, 1)
Calls dfs(maze, 'the', 0, 1, 1)
- Current Cell: (0, 1)
- Current Character in Maze: 'a'
- Current Character in Word: 'h'
- Index: 1
- Characters do not match: Backtracks and return False
Iteration 4: word_search(maze, 'the')
Calls dfs(maze, 'the', 1, 0, 0)
- Current Cell: (1, 0)
- Current Character in Maze: 't'
- Current Character in Word: 't'
- Index: 0
- Mark (1, 0) as visited
- Explores neighbors: (2, 0), (0, 0), (1, 1), (1, -1)
Iteration 5: dfs(maze, 'the', 1, 1, 1)
Calls dfs(maze, 'the', 1, 1, 1)
- Current Cell: (1, 1)
- Current Character in Maze: 'h'
- Current Character in Word: 'h'
- Index: 1
- Mark (1, 1) as visited
- Explores neighbors: (2, 1), (0, 1), (1, 2), (1, 0)
Iteration 6: dfs(maze, 'the', 1, 2, 2)
Calls dfs(maze, 'the', 1, 2, 2)
- Current Cell: (1, 2)
- Current Character in Maze: 'e'
- Current Character in Word: 'e'
- Index: 2
- Mark (1, 2) as visited
- Word found: Return True
Backtracking
After finding the word, we backtrack to unmark the visited cells.
Step 1: Unmark (1, 2)
- Current Cell: (1, 2)
- Unmark (1, 2)
Step 2: Unmark (1, 1)
- Current Cell: (1, 1)
- Unmark (1, 1)
Step 3: Unmark (1, 0)
- Current Cell: (1, 0)
- Unmark (1, 0)
Detailed Function Call Diagram for DFS Execution
Function Call Diagram
word_search(maze, 'the')
-> dfs(maze, 'the', 0, 0, 0)
-> (maze[0][0] == 't') == (word[0] == 't') -> True
-> Explore neighbors: (1, 0), (-1, 0), (0, 1), (0, -1)
-> dfs(maze, 'the', 1, 0, 1)
-> (maze[1][0] == 't') != (word[1] == 'h') -> False
-> dfs(maze, 'the', 0, 1, 1)
-> (maze[0][1] == 'a') != (word[1] == 'h') -> False
-> dfs(maze, 'the', 1, 0, 0)
-> (maze[1][0] == 't') == (word[0] == 't') -> True
-> Explore neighbors: (2, 0), (0, 0), (1, 1), (1, -1)
-> dfs(maze, 'the', 1, 1, 1)
-> (maze[1][1] == 'h') == (word[1] == 'h') -> True
-> Explore neighbors: (2, 1), (0, 1), (1, 2), (1, 0)
-> dfs(maze, 'the', 1, 2, 2)
-> (maze[1][2] == 'e') == (word[2] == 'e') -> True
-> Word found, return True
Diagram Explanation
word_search
starts from each cell and callsdfs
.dfs(maze, 'the', 0, 0, 0)
starts from cell (0, 0) with the first character 't' and succeeds.dfs(maze, 'the', 1, 0, 1)
moves to cell (1, 0) with the second character 'h' and fails.dfs(maze, 'the', 0, 1, 1)
moves to cell (0, 1) with the second character 'h' and fails.dfs(maze, 'the', 1, 0, 0)
starts from cell (1, 0) with the first character 't' and succeeds.dfs(maze, 'the', 1, 1, 1)
moves to cell (1, 1) with the second character 'h' and succeeds.dfs(maze, 'the', 1, 2, 2)
moves to cell (1, 2) with the third character 'e' and succeeds.- The word 'the' is found, and the function returns True.
Why Unmarking is Required in the Algorithm
Unmarking cells in the DFS algorithm is required to ensure that we correctly handle multiple starting points and overlapping paths. Let's break down the reasons for unmarking:
1. Multiple Starting Points
In a word search problem, we start the search from multiple cells in the maze. If we don't unmark cells after each search, previously marked cells would incorrectly block subsequent searches starting from different cells.
2. Overlapping Paths
The DFS algorithm explores all possible paths in the maze to find the word. During the search, it may traverse overlapping paths. Unmarking ensures that these cells are available for exploration in other potential paths.
3. Backtracking
The essence of DFS is to explore all possible paths. When a path does not lead to the desired result (i.e., finding the word), the algorithm backtracks and unmarks the cells to allow other paths to be explored.
Example
Consider the maze:
[['t', 'a', 'b'],
['t', 'h', 'e'],
['o', 'f', 'g']]
When searching for the word "the", starting from cell (0, 0) and finding that cell (1, 0) does not lead to the word, the algorithm backtracks and unmarks cell (1, 0). This allows subsequent searches starting from different cells, such as (1, 0) and exploring further cells (1, 1) and (1, 2).
Unmarking ensures the correctness and completeness of the search, allowing the algorithm to explore every possible path and handle multiple starting points effectively.
Support Our Efforts and Earn Together 🚀
Visit https://parucodes.github.io/ today and start your journey to becoming a fast, accurate, and confident touch typist.
If you find our website useful and want to support us, consider joining the exciting world of Bitcoin mining on your mobile phone. Follow this link: Mine PI Bitcoin and use my username prarthanadp as your invitation code. With the referral code prarthanadp, you'll receive a special referral bonus.
Thank you for your support! Let's grow and earn together! 🌟
Comments
Post a Comment