What if you could teach a computer to find its way out of any maze without getting lost?
Why Rat in a Maze Problem in DSA Rust?
Imagine you are in a big maze trying to find a path from the start to the exit. You try every turn by guessing and remembering where you have been, but it is easy to get lost or miss the right way.
Manually checking every path is slow and confusing. You might go in circles or miss the exit because you don't keep track of your steps well. It's hard to know if you tried all possible ways.
The Rat in a Maze problem uses a smart way to explore paths step-by-step and backtrack if a path is wrong. It remembers where it has been and tries new ways until it finds the exit or knows there is no way out.
let mut path = Vec::new(); // guess moves and check manually if can_move_right() { path.push('R'); } else if can_move_down() { path.push('D'); }
fn solve_maze(x: usize, y: usize, maze: &Vec<Vec<u8>>, path: &mut Vec<(usize, usize)>) -> bool {
if reached_exit(x, y) { return true; }
if safe_move(x, y, maze) {
path.push((x, y));
if solve_maze(x + 1, y, maze, path) || solve_maze(x, y + 1, maze, path) {
return true;
}
path.pop();
}
false
}This method lets you find a path through complex mazes automatically, without guessing or missing any options.
Robots exploring unknown buildings use similar logic to find safe paths and avoid obstacles.
Manual pathfinding is confusing and error-prone.
Backtracking explores all paths smartly and remembers steps.
It helps find solutions or prove none exist in a maze.
Practice
Rat in a Maze problem in data structures?Solution
Step 1: Understand the problem goal
The Rat in a Maze problem asks to find a path from the start cell (usually top-left) to the destination cell (usually bottom-right) in a maze represented by a grid.Step 2: Identify the correct goal
The goal is not counting cells, sorting, or shortest distance but finding a valid path through allowed cells.Final Answer:
Find a path from the start to the destination in a maze -> Option AQuick Check:
Goal = Find path [OK]
- Confusing pathfinding with counting cells
- Thinking it finds shortest path always
- Mixing it with sorting or graph distance problems
Solution
Step 1: Check parameter types for maze and coordinates
The maze is a 2D grid, so it should be a reference to a vector of vectors of integers (&Vec). Coordinates are usize for indexing.Step 2: Check return type and path parameter
The function returns bool to indicate success and uses a mutable path vector to store the route.Final Answer:
fn solve_maze(maze: &Vec, x: usize, y: usize, path: &mut Vec<(usize, usize)>) -> bool -> Option DQuick Check:
Correct signature uses references and bool return [OK]
- Passing maze by value causing unnecessary copying
- Using wrong coordinate types (i32 instead of usize)
- Returning wrong types like i32 or Vec instead of bool
fn main() {
let maze = vec![
vec![1, 0, 0, 0],
vec![1, 1, 0, 1],
vec![0, 1, 0, 0],
vec![1, 1, 1, 1],
];
let mut path = Vec::new();
if solve_maze(&maze, 0, 0, &mut path) {
println!("Path found: {:?}", path);
} else {
println!("No path found");
}
}
fn solve_maze(maze: &Vec, x: usize, y: usize, path: &mut Vec<(usize, usize)>) -> bool {
let n = maze.len();
if x == n - 1 && y == n - 1 {
path.push((x, y));
return true;
}
if x < n && y < n && maze[x][y] == 1 {
path.push((x, y));
if x + 1 < n && solve_maze(maze, x + 1, y, path) {
return true;
}
if y + 1 < n && solve_maze(maze, x, y + 1, path) {
return true;
}
path.pop();
}
false
}Solution
Step 1: Trace the recursive calls from (0,0)
Start at (0,0) which is 1 (allowed). Try moving down to (1,0) which is 1, then (2,0) is 0 (blocked), so backtrack. Then try right from (1,0) to (1,1) which is 1.Step 2: Continue path to destination
From (1,1), down to (2,1) is 1, then down to (3,1) is 1, right to (3,2) is 1, and right to (3,3) is 1 (destination). Path is [(0,0),(1,0),(1,1),(2,1),(3,1),(3,2),(3,3)].Final Answer:
Path found: [(0, 0), (1, 0), (1, 1), (2, 1), (3, 1), (3, 2), (3, 3)] -> Option AQuick Check:
Recursive path = Path found: [(0, 0), (1, 0), (1, 1), (2, 1), (3, 1), (3, 2), (3, 3)] [OK]
- Assuming path goes right first instead of down
- Not backtracking correctly on blocked cells
- Confusing coordinates order in path
fn solve_maze(maze: &Vec, x: usize, y: usize, path: &mut Vec<(usize, usize)>) -> bool {
let n = maze.len();
if x == n - 1 && y == n - 1 {
path.push((x, y));
return true;
}
if x < n && y < n && maze[x][y] == 1 {
path.push((x, y));
if solve_maze(maze, x + 1, y, path) {
return true;
}
if solve_maze(maze, x, y + 1, path) {
return true;
}
path.pop();
}
false
}Solution
Step 1: Analyze recursive calls for boundary safety
The recursive calls use x+1 and y+1 without checking if they exceed maze size, risking out-of-bounds panic.Step 2: Fix by adding boundary checks before recursion
Adding checks like x + 1 < n and y + 1 < n before calling solve_maze prevents invalid indexing.Final Answer:
Add boundary checks before recursive calls to avoid out-of-bounds -> Option CQuick Check:
Boundary checks prevent panic [OK]
- Ignoring index bounds causing runtime panic
- Changing maze to mutable unnecessarily
- Removing path.pop() causing wrong paths
Solution
Step 1: Understand requirement to find all paths
Finding all paths means exploring every possible route without stopping at the first success.Step 2: Use recursion to explore all moves and collect paths
Return a vector of paths and do not return early. Backtrack properly to explore all options.Final Answer:
Return a vector of paths and explore all possible moves recursively without stopping at first success -> Option BQuick Check:
Explore all paths recursively [OK]
- Stopping recursion early losing other paths
- Using BFS only for shortest path, not all paths
- Marking visited permanently blocking other paths
Ready to prove it?
Pass the test and this pattern moves unknown
