1.2.37 · D3Introduction to Programming (Python)

Worked examples — Recursion — call stack visualization, base case, recursive case

2,709 words12 min readBack to topic

The scenario matrix

Every recursive problem lives in one of these cells. The last column names the example that covers it.

# Cell (scenario class) What makes it tricky Covered by
A Normal shrink-by-one ordinary recursive case, one branch Example 1 (factorial)
B Base case is the WHOLE input input already tiny, no recursion runs Example 2 (fact(0), summ([]))
C Degenerate / invalid input negative or empty — does it stop? Example 3 (fact(-1))
D Two base cases at once need two stops, not one Example 4 (Fibonacci)
E Branching (tree-shaped) recursion each call spawns many calls Example 4 (Fibonacci)
F Shrink-by-halving (limiting depth) problem drops fast, depth is small Example 5 (power via halving)
G Order matters: work before vs after the call winding vs unwinding (still linear) Example 6 (print order)
H Real-world word problem translate story → base + recursive case Example 7 (Russian dolls)
I Exam-style twist subtle bug you must spot Example 8 (missing return)

Example 1 — Cell A: the ordinary shrink-by-one

Figure — Recursion — call stack visualization, base case, recursive case

Example 2 — Cell B: the base case IS the whole input


Example 3 — Cell C: degenerate / invalid input


Example 4 — Cells D & E: two base cases + branching

Figure — Recursion — call stack visualization, base case, recursive case

Example 5 — Cell F: shrink-by-halving (small depth)


Example 6 — Cell G: order matters (winding vs unwinding)

def up(n): if n < 0: return up(n-1) print(n) # AFTER the call

Note: each of these makes **exactly one** recursive call per frame — this is *linear* recursion, not branching. Only the *position* of the work changes.
**Forecast:** For `down(3)` and `up(3)`, predict both printed sequences before reading.

**Step 1 — `down`: print happens during winding.**
The `print(n)` runs *before* the recursive call, so it fires as frames go **down**: `3, 2, 1, 0`.
*Why this step?* Work placed before the recursive call executes on the descent.

**Step 2 — `up`: print happens during unwinding.**
The `print(n)` runs *after* the sub-call fully finishes, so it fires as frames **pop back up**: `0, 1, 2, 3`.
*Why this step?* Work placed after the recursive call waits for the whole subtree, then runs on the way back — this is exactly how *post-order* [[Tree and Graph Traversal]] works.

**Verify:** `down(3)` → `3,2,1,0`; `up(3)` → `0,1,2,3`. ✅ Same recursion, mirror-image output — the single line's position decides everything.
Figure — Recursion — call stack visualization, base case, recursive case

Example 7 — Cell H: real-world word problem


Example 8 — Cell I: exam-style twist (spot the bug)


Recall Quick self-test on the matrix

Which cell is fact(0)? ::: Cell B — base case is the whole input, zero recursive calls. Which cell would fib fall into and why two base cases? ::: Cells D & E — branching recursion, and the n-2 branch can leap past 0, so we catch both 0 and 1. Moving print after the recursive call changes which phase it runs in? ::: From winding (descent) to unwinding (return), reversing the output order. Why does halving-power need far fewer frames than shrink-by-one? ::: It reaches the base in about log₂(e) recursive calls instead of e.