Recursion (define tell-story (lambda () (print ‘’Once upon a time there was a mountain. ‘’) (print ‘’On the mountain, there was a temple. ‘’) (print ‘’In the temple, there was an old monk telling a story. ‘’) (print “What is the story? It is: ”) (tell-story)) Definition: A recursive procedure is a procedure that calls itself.
Recursive Problems A problem that can be reduced to a simpler version of itself plus some simple operations When we’re solving a recursive problem, we want the function to stop somewhere-> Base Case Classic example: factorial – 1! = 1 – 2! = 2 * 1 – 3! = 3 * 2 * 1 – n! = n * (n-1) * (n-2) * … * 2 * 1 – 0! = 1
Factorial in Scheme (define (factorial x) (if (= x 1) 1 (* x (factorial (- x 1))))) Review: If - used to break code into cases (if predicate consequent alternate) –Predicate is the test. –Consequent executes if predicate is true. –Alternate executes if predicate is false.
Example of Factorial (define (factorial x) (if (= x 1) 1 (* x (factorial (- x 1))))) (factorial 4): Definition: A recursive process has deferred operations. (* 4 (* 3 (factorial 2))) (* 4 (* 3 (* 2 (factorial 1)))) (* 4 (* 3 (* 2 1))) (* 4 (* 3 2)) (* 4 6) 24 (* 4 (factorial 3))
How to make recursive procedures: We want to make a procedure that solves a problem with input size n 1. Pretend you known how to solve the problem for input sizes 1, 2,…, n-1 2. Use smaller instances and simple operations to formulate solution for input of size n 3. Identify base case and solve it directly
Example: Fibonacci (define (fib n) (cond ((= n 1) 1) <- base case ((= n 2) 2) <- base case (else (+ (fib (- n 1)) (fib (- n 2)))))) The cond structure: for when there are multiple cases. (cond ((predicate1) consequent1) ((predicate2) consequent2) … (else alternate))
Iterative Functions The problem with recursive processes: deferred operations takes up space. An iterative procedure uses constant space. A “true” iterative procedure has no self-calls. public int factorial(int n) { int answer = 1; for (int i = 1; i <=n; i++) { answer *= n; } return answer; } NOTE: This example is written in Java, not Scheme!
Scheme’s version of Iterative Tail Recursion- recursion with no deferred operations. (tell-story) is actually an example of tail recursion. Has counter and keeps track of current answer.
Tail Recursive Factorial (define (factorial n) (fact-helper 1 1 n)) (define (fact-helper product counter n) (if (> counter n) product (fact-helper (* product counter) (+ counter 1) n))))
Iterative Factorial Example (define (factorial n) (fact-helper 1 1 n)) (define (fact-helper product counter n) (if (> counter n) product (fact-helper (* product counter) (+ counter 1) n)))) Ex: (factorial 3) (fact-helper 1 1 3) (fact-helper 1 2 3) (fact-helper 2 3 3) (fact-helper 6 4 3) 6
Summary Recursion Used to solve problems that can be broken into smaller instances plus some simple operations A function keeps calling itself until some base case Problem: deferred operations take up space Iteration Uses a counter. Always keeps track of current “solution” No deferred operations. No self-calls Tail Recursion Scheme’s version of iterative Self-calls with no deferred operations