Recursion
Modified 2023-07-23
Recursion is important to understand for some of the more complex data structures. Rules to understand recursion:
- develop a solid base case base case, before even thinking about the recursive one (really important!!) => stops the recursion
- then you implement the recursive step, which includes 3 phases
- pre
the code ran before calling the recursive call, that isn't part of the base case
- recursive call
calling the function recursively
- post
the code ran after, when the recursion starts unrolling again
Typescript
Recursion is usually explained when calculating factorial, but the example too simple. Better with maze solver.
- :: path
- X
wall
- E
end
- S
start
XXXXXXXXEXXXX X XXXX XSXXXXXXXXXXX
Base Case
- it's a wall => invalid state
- out of bounds => invalid state
- it's the end => valid state
- seen the tile before => invalid state
Recursive Case
Checking every direction
Code
const dir = [
[0, 1], // top
[1, 0], // right
[0, -1], // down
[-1, 0] // left
]
function walk(pos: Point, maze: string[], wall: string, end: Point, seen: boolean[][], path: Point[]): boolean {
// base case
if (pos.x < 0 || pos.x >= maze[0].length || // string.length
pos.y < 0 || pos.y >= maze.length) {
return false
}
if (maze[pos.y][pos.x] == wall) return false
if (pos.x == end.x && pos.y == end.y) {
path.push(end) // the last tile doesn't get added by the pre-step, since the recursion
// unrolls before it can push the lost value
return true
}
if (seen[pos.y][pos.x]) return false
// recursive case
// 1. pre => reaching this point means the point is valid
seen[pos.y][pos.x] = true
path.push(pos)
// 2. recurse => look for a new direction
for (let i = 0; i < dir.length; i++) {
const [x, y] = dir[i]
if (walk({
x: pos.x + x,
y: pos.y + y
}, maze, wall, end, seen, path)) {
return true
}
}
// 3. post => reaching this, after recursion unrolls, means the base case was hit
path.pop()
return false
}
export default function solve(maze: string[], wall: string, start: Point, end: Point): Point[] {
const seen: boolean[][] = []
const path: Point[] = []
for (let i = 1; i < maze.length; ++i) {
seen.push(new Array(maze[0].length).fill(false))
}
walk(start, maze, wall, end, seen, path)
return path
}