Exercise 1: Recursive Fibonacci and Its Real Call Count — Possible Solution ==================================================================== THE FUNCTION ------------------------------ fun fib(n) { if (n <= 1) { return n; } return fib(n - 1) + fib(n - 2); } print fib(10); RESULT ------------------------------ 55 (correct: 0,1,1,2,3,5,8,13,21,34,55 -- the 10th Fibonacci number) TOTAL RECURSIVE CALLS FOR fib(10) ------------------------------ 177 total calls to fib() (measured by instrumenting a plain Python equivalent with a call counter, since the exercise's own Wisp interpreter doesn't expose a call counter directly, and the recursive shape is identical either way) WHY THIS WORKS AS AN ANSWER ------------------------------ 177 is dramatically more than 10, and that's the whole point of this exercise. fib(10) does NOT ask "what's the 10th Fibonacci number" once -- it asks fib(9) and fib(8), each of which asks two more smaller fib() calls, and so on. fib(8) gets computed TWICE: once as part of fib(9)'s own call to fib(7)+fib(8)... no wait, more precisely: fib(10) calls fib(9) and fib(8). fib(9) calls fib(8) and fib(7). So fib(8) is computed once directly from fib(10) and once again from fib(9) -- a second, entirely separate, entirely redundant recursive descent down to n=0 and n=1 all over again. This is the classic "naive recursion recomputes the same subproblem exponentially many times" pattern -- the same shape Algorithms & Complexity's own naive-Fibonacci chapter (algo1-9) measured directly: an O(2^n) call count, not O(n). 177 calls for fib(10) is a small, concrete instance of exactly that blowup; fib(30) would already be in the millions of calls using this same naive shape, entirely because of duplicated work, not because computing a single Fibonacci number is inherently that expensive. Fixing it (memoization, or an iterative version using a while loop instead of recursion) is out of this chapter's own scope, but the call count above is the concrete number that motivates why it would matter.