Predict and trace recursive processes (linear vs tree recursion), then implement recursive, iterative, and memoized procedures to compare process shape and cost.
Before running anything, **predict** the returned value and the exact `log` list.
Code to reason about:
```python
def fact_log(n, log):
log.append(f"enter {n}")
if n == 0:
log.append("base")
return 1
result = n * fact_log(n - 1, log)
log.append(f"exit {n} -> {result}")
return result
def run_fact_log():
log = []
value = fact_log(3, log)
return value, log
```
1) What does `run_fact_log()` return?
2) Which happens first: all the `enter ...` messages, or some `exit ...` messages?
After you write your prediction as a comment, run it to check.These two procedures both compute `a + b` using only `inc` and `dec`, but they generate different **process shapes**.
Trace by looking at the logged `(a, b)` pairs.
Tasks:
1) Predict the logs for `add_rec_log(4, 5)` and `add_iter_log(4, 5)` (write your prediction as comments).
2) Run the code to check.
3) Explain (in your own words): which one is a **linear recursive process** and which one is an **iterative process**?
```python
def inc(x):
return x + 1
def dec(x):
return x - 1
```
A function `f` is defined by: - `f(n) = n` if `n < 3` - `f(n) = f(n-1) + 2*f(n-2) + 3*f(n-3)` if `n >= 3` Tasks (in order): 1) **Implement** `f_recursive(n)` using a direct recursive translation. 2) **Implement** `f_iter(n)` that computes the same values but using an **iterative process** (carry state explicitly). 3) **Extend**: implement `f_memo(n, memo=None)` using recursion + memoization (a dictionary cache). Prediction checkpoint (do this before coding): - Compute by hand: `f(3)`, `f(4)`, `f(5)`. Your functions should all agree for the same input.