# CS3L OaW Lecture 7 : Embedded, Tail, and Advanced Recursion

## Tail Recursion vs. Embedded Recursion

### Short example : sum-0-to-n

• We have seen that recursion, as we know it, almost always leaves us with work to do.
```;; sum-0-to-n

(define (sum-0-to-n n)
(if (zero? n)
0
(+ n (sum-0-to-n (- n 1)))))```
• Modeling it:
```: (model (sum-0-to-n 3))
(+ 3 (sum-0-to-n 2))
(+ 3 (+ 2 (sum-0-to-n 1)))
(+ 3 (+ 2 (+ 1 (sum-0-to-n 0)))) ;; base case
(+ 3 (+ 2 (+ 1 0)))              ;; now going back up, "cleaning up"
(+ 3 (+ 2 1))
(+ 3 3)
6```
• Which means we had to work our way down to the base case, then work our way back up to the top.

#### (it's also called linear recursion, because it only uses one recursive call in the recursive case)

• Analogy: Let's say you were commissioned to measure a large distance, like the distance from here to the best New York-Style Pizza in Berkeley, Arinell's pizza on Shattuck near BofA. Solving the problem using embedded recursion:
1. Check if you are there yet
2. If not, take a step, put a mark on a piece of paper, and restart the problem (but now you're one step closer)
3. When you are done, then you have to count up all the marks!

### Let's rethink the problem : sum-0-to-n-tail

• Would it be possible to work our way down and somehow keep track of the answer as we go, and when we get to the bottom (base) case, return that answer?

#### This is called tail recursion, or iteration.

• Using our analogy, we'd instead write down how many steps we'd taken so far as a running total, and when we were done, the answer would be there already!
• Official definition: the recursive call is not embedded within an expression that needs to wait for the completion of the call
• Unofficial definition: there's nothing to the left of the recursive call, like a +, se, or and

#### Often it is easier to solve a recursive problem using tail recursion! ...some find this the more intuitive approach.

• How would we rewrite sum-0-to-n so that it keeps track of the sum?
```;; sum-0-to-n-tail
;;
;; INPUTS       : A single number, n
;; REQUIRES     : The number be a positive integer
;; SIDE-EFFECTS : None
;; RETURNS      : The sum of all the integers from 0 to n.
;; EXAMPLE      : (sum-0-to-n-tail 3) ==> 6 ;; 0 + 1 + 2 + 3 = 6

: (define (sum-0-to-n-tail n)
==>

: (define (sum-0-to-n-tail-helper n sum-so-far)
==>
==>
==>```
• Modeling it...
```: (model (sum-0-to-n-tail 3))
(sum-0-to-n-tail-helper 3 0)
(sum-0-to-n-tail-helper 2 3)
(sum-0-to-n-tail-helper 1 5)
(sum-0-to-n-tail-helper 0 6) ;; base case
6                            ;; ...done! No need to "clean up"```

### Another example: my-count vs. my-count-tail

• Recall embedded recursion version of my-count:
```(define (my-count s)
(if (empty? s)
0
(+ 1 (my-count (bf s)))))```
• Modeling it...
```: (model (my-count '(a b c)))
(+ 1 (my-count '(b c)))
(+ 1 (+ 1 (my-count '(c))))
(+ 1 (+ 1 (+ 1 (my-count '()))))  ;; base case
(+ 1 (+ 1 (+ 1 0)))               ;; cleaning up
(+ 1 (+ 1 1))
(+ 1 2)
3```
• Now let's write a tail recursive my-count-tail:
```: (define (my-count-tail s)
==>

: (define (mct-helper s count-so-far) ;; shortened name for convenience
==>
==>
==>```
• Modeling it...
```: (model (my-count-tail '(a b c)))
(mct-helper '(a b c) 0)
(mct-helper '(b c) 1)
(mct-helper '(c) 2)
(mct-helper '() 3)     ;; base case, no clean up needed!
3```

### More examples: count-even-and-odds

```;; count-even-and-odds
;;
;; INPUTS       : A sentence of integers, s
;; REQUIRES     : The sentence consist only of integers
;; SIDE-EFFECTS : None
;; RETURNS      : A two-word sentence, wherein the first word
;;              : is the number of even numbers in the sentence, and
;;              : the second word is the number of odd numbers
;; EXAMPLE      : (count-even-and-odds '(1 2 3 0 -4 8 5)) ==> (4 3)
;;              : (count-even-and-odds '(7 9 5 795)) ==> (0 4)
;;              : (count-even-and-odds '(2 4 999998)) ==> (3 0)
;;              : (count-even-and-odds '()) ==> (0 0)

: (define (count-even-and-odds s)
==>

: (define (ceao-helper
==>
==>
==>
==>
==>```

### More examples: all-increasing?

```;; all-increasing?
;;
;; INPUTS       : A sentence, s
;; REQUIRES     : The sentence consist only of integers,
;;              : AND the sentence be non-empty
;; SIDE-EFFECTS : None
;; RETURNS      : #t if the sentence is in strictly increasing order, else #f
;; EXAMPLE      : (all-increasing? '(-50 1 2 3 5)) ==> #t
;;              : (all-increasing? '(1 2 3 0)) ==> #f

: (define (all-increasing? s)
==>

: (define (ai-helper?
==>
==>
==>
==>```

### More examples: longest-win-streak

```;; longest-win-streak
;;
;; INPUTS       : A sentence of w's and l's, s
;; REQUIRES     : The sentence consist only of w's and l's
;;              : AND the sentence be non-empty
;; SIDE-EFFECTS : None
;; RETURNS      : The count of the team's longest winning streak
;; EXAMPLE      : (longest-win-streak '(l l l l)) ==> 0
;;              : (longest-win-streak '(l w w w l w w l l l l w)) ==> 3

: (define (longest-win-streak s)
==>

: (define (lws-helper
==>
==>
==>
==>
```

### Pascal's triangle : pascal

• We'd like to be able to calculate elements of Pascal's triangle
• The triangle is used in many places!
• Combinatorics
• How many ways are there of choosing C things from R possible choices?
• E.g., How many ways are there of choosing C=2 cards from a deck of R=5 cards?
• Answer: look in the table under (C,R) = (2,5) and you see there are 10 ways!
• Polynomial multiplication
• What are the coefficients of the terns (x + y)5?
• 1 x5 + 5 x4y + 10 x3y2 + 10 x2y3 + 5 xy4 + 1 y5
• See any correlation between the bold numbers above and the 5th row (R=5) ?

#### columns (C) r o w s (R) 0 1 2 3 4 5 ... 0 1           ... 1 1 1         ... 2 1 2 1       ... 3 1 3 3 1     ... 4 1 4 6 4 1   ... 5 1 5 10 10 5 1 ... ...  ... .. ... ... ... ... ... Pascal's Triangle

• The rule for calculating the elements triangle is:
• Every element is the sum of the two elements directly above (north) and to the immediate upper left (northeast)
• More specifically:

pascal(C,R) = pascal(C-1,R-1) + pascal(C,R-1)

• Let's write it:
```(define (pascal C R)
==>
==>
==>```
• Exercise for the ambitious: rewrite pascal to use the formula (! = factorial, you will have to write that also):
`pascal(C,R) = R! / ((R-C)! C!)`

### Pair all prefixes with suffixes : pair-all

• We want to take a sentence of prefixes and one of suffixes and return a sentence with pairings of all the prefixes with all the suffixes
```(pair-all '(a b c d) '(1 2 3))
;; ==> (a1 a2 a3 b1 b2 b3 c1 c2 c3 d1 d2 d3)

(pair-all '(to re on) '(ad ward ly))
;; ==> (toad toward toly read reward rely onad onward only)```
• Inspiration! Divide the problem into two parts:
1. (append-prefix prefix suffixes) ;; append prefix word to all words in suffixes
2. (pair-all prefixes suffixes) ;; send all prefixes in prefixes to append-prefix
```(define (append-prefix prefix suffixes)
==>
==>
==>

(define (pair-all prefixes suffixes)
==>
==>
==>
==>
==>
==>
==>```
• Exercise for the ambitious: Rewrite the code so that instead of looping on prefixes first and suffixes next (e.g., a1 a2 a3 b1 b2 ...) it loops on suffixes first and prefixes next (e.g., a1 b1 c1 d1 a2 b2 ...)

• Linear
• Embedded
• Tail
• Non-linear
• Nested