Recursion To understand recursion one must first understand








![Clojure Syntax (defn couple [a y] (if (empty? y) '() (cons (list a (first Clojure Syntax (defn couple [a y] (if (empty? y) '() (cons (list a (first](https://slidetodoc.com/presentation_image_h2/1925fbe7755c8986b09a6c3efaf7385a/image-9.jpg)



![Clojure Syntax (defn ins [a ss] (if (empty? ss) '() (cons a (first ss)) Clojure Syntax (defn ins [a ss] (if (empty? ss) '() (cons a (first ss))](https://slidetodoc.com/presentation_image_h2/1925fbe7755c8986b09a6c3efaf7385a/image-13.jpg)








![Clojure Syntax (defn insert [n lon] (cond (empty? lon) (list n) (> n (first Clojure Syntax (defn insert [n lon] (cond (empty? lon) (list n) (> n (first](https://slidetodoc.com/presentation_image_h2/1925fbe7755c8986b09a6c3efaf7385a/image-22.jpg)

![Anonymous functions and list membership test in Clojure > ( (fn [x y] (+ Anonymous functions and list membership test in Clojure > ( (fn [x y] (+](https://slidetodoc.com/presentation_image_h2/1925fbe7755c8986b09a6c3efaf7385a/image-24.jpg)
![Subset in Clojure (cf. case sensitive Scheme) (defn subset? [ss s] (or (empty? ss) Subset in Clojure (cf. case sensitive Scheme) (defn subset? [ss s] (or (empty? ss)](https://slidetodoc.com/presentation_image_h2/1925fbe7755c8986b09a6c3efaf7385a/image-25.jpg)


![(defn third [x] (second (rest x))) (defn ops [e] ; Clojure code "e is (defn third [x] (second (rest x))) (defn ops [e] ; Clojure code "e is](https://slidetodoc.com/presentation_image_h2/1925fbe7755c8986b09a6c3efaf7385a/image-28.jpg)


![(Alternative syntax in Clojure (not equivalent or robust)) (defn ops [e] ; e is (Alternative syntax in Clojure (not equivalent or robust)) (defn ops [e] ; e is](https://slidetodoc.com/presentation_image_h2/1925fbe7755c8986b09a6c3efaf7385a/image-31.jpg)
- Slides: 31
Recursion To understand recursion, one must first understand recursion. cs 3180(Prasad) L 14 Recur+Clojure 1
Specifying Incremental Work 0 -> f(0) 1 -> f(1) D 1 . . . n n+1 cs 3180(Prasad) Dn -> f(n) -> f(n+1) L 14 Recur 2
Divide and Conquer Problem Subproblem 1 decomposition Subproblem 2 recursion primitive Subsolution 1 Subsolution 2 composition Solution cs 3180(Prasad) L 14 Recur 3
Cartesian Product > (cart 2 '(1 2) '(a b)) ( (1 a) (1 b) (2 a) (2 b) ) > (cart 2 '(0 1 2) '(a b)) ( (0 a) (0 b) (1 a) (1 b) (2 a) (2 b) ) > (couple ' 1 '(b c)) ( (1 b) (1 c) ) > (couple ' 1 '(a b c)) ( (1 a) (1 b) (1 c) ) cs 3180(Prasad) L 14 Recur 4
Divide and Conquer (cart 2 '(a b) '(1)) (couple ' a '(1)) car/cdr (cart 2 '(b) '(1)) recursion “primitive” ((a 1)) ((b 1)) append ((a 1) (b 1)) cs 3180(Prasad) L 14 Recur 5
Different Problems; Same pattern cs 3180(Prasad) L 14 Recur 6
Scheme Definition (define (cart 2 x y) (if (null? x) '() (append (couple (car x) y) (cart 2 (cdr x) y) ) (define (couple a y) (if (null? y) '() (cons (list a (car y)) (couple a (cdr y)) ) cs 3180(Prasad) L 14 Recur 7
Alternate Syntax : lambda (define cart 2 (lambda (x y) (if (null? x) '() (append (couple (car x) y) (cart 2 (cdr x) y) ) ) (define couple (lambda (a y) (if (null? y) '() (cons (list a (car y)) (couple a (cdr y)) ) ) cs 3180(Prasad) L 14 Recur 8
Clojure Syntax (defn couple [a y] (if (empty? y) '() (cons (list a (first y)) (couple a (rest y)) ))) (defn cart 2 [x y] (if (empty? x) '() (concat (couple (first x) y) (cart 2 (rest x) y) ))) cs 3180(Prasad) L 14 Recur 9
Powerset > (powerset '(2)) ( ( ) (2) ) > (powerset '(1 2) ) ( (1) (1 2) () (2) ) > (powerset '(0 1 2)) ( (0 1) (0 1 2) (0 2) (1 2) () (2) ) Subsets of {0, 1, 2} with 0 are equinumerous with subsets of {0, 1, 2} without 0. cs 3180(Prasad) L 14 Recur 10
(define (powerset s) (if (null? s) '(()) (append (ins (car s) (powerset (cdr s)) ) )) (define (ins a ss) (if (null? ss) '() (cons a (car ss)) (ins a (cdr ss)) ) )) cs 3180(Prasad) L 14 Recur 11
Alternate Syntax : let (define (powerset s) (if (null? s) '(()) (let ( (aux (powerset (cdr s))) ) (append (ins (car s) aux ) ) )) (define (ins a ss) (if (null? ss) '() (cons a (car ss)) (ins a (cdr ss)) ) )) cs 3180(Prasad) L 14 Recur 12
Clojure Syntax (defn ins [a ss] (if (empty? ss) '() (cons a (first ss)) (ins a (rest ss)) ) )) (defn powerset [s] (if (empty? s) '(()) (let [aux (powerset (rest s))] (concat (ins (first s) aux ) ) )) cs 3180(Prasad) L 14 Recur 13
Related problems; Different Patterns cs 3180(Prasad) L 14 Recur 14
Remove-First-Top. Level (define (rm-fst-top sym lis) (if (null? lis) '() (if (eq? sym (car lis)) (cdr lis) (cons (car lis) (rm-fst-top sym (cdr lis)) ) ) > (rm-fst-top • 'a '(b (b a) a b a)) = (b (b a) Linear recursion cs 3180(Prasad) L 14 Recur 15
Alternate Syntax : if => cond (define (rm-fst-top sym lis) (cond ( (null? lis) '()) ( (eq? sym (car lis)) (cdr lis) ) ( else (cons (car lis) (rm-fst-top sym (cdr lis)) ) ) > (rm-fst-top • 'a '(b (b a) a b a)) = (b (b a) Linear recursion cs 3180(Prasad) L 14 Recur 16
Remove-All-Top. Level (define (rm-all-top sym lis) (cond ( (null? lis) '()) ( (eq? sym (car lis)) (rm-all-top sym (cdr lis) ) ) ( else (cons (car lis) (rm-all-top sym (cdr lis))) ) > (rm-all-top 'a '(b (b a) a b a)) = > (rm-all-top ' (b a) '(b (b a) a b a)) (b (b a) b) = (b (b a) a b a) • Linear recursion cs 3180(Prasad) L 14 Recur 17
Remove-All-Expression-Top. Level (define (rm-all-top exp lis) (cond ( (null? lis) '()) ( (equal? exp (car lis)) (rm-all-top exp (cdr lis) ) ) ( else (cons (car lis) (rm-all-top exp (cdr lis)))) ) ) > (rm-all-top ' (b a) '(b (b a) a b a)) = (b a b a) • Linear recursion cs 3180(Prasad) L 14 Recur 18
Remove-All (define (rm-all sym ll) (cond ( (null? ll) '()) ( (symbol? (car ll)) (if (eq? sym (car ll)) ( rm-all sym (cdr ll) ) ( cons (car ll) (rm-all sym (cdr ll)) ) (else (cons (rm-all sym (car ll)) (rm-all sym (cdr ll)) ) ) > (rm-all ' a '(b (b a) a b a)) = (b (b) b) – Double recursion cs 3180(Prasad) L 14 Recur 19
rm-all : Structural recursion • Empty list (Basis case) (rm-all 'a '()) • First – Atom (Recursive case) (rm-all 'a '(a b c a)) (rm-all 'a '(b b c a)) • First - Nested list (Recursive case) (rm-all 'a '((a b c) d (a))) (rm-all 'a '(b (a b c) d (a))) cs 3180(Prasad) L 14 Recur 20
Insertion sort (Note: creates a sorted copy) (define (insert n lon) (cond ((null? lon) (list n)) ((> n (car lon)) (cons (car lon) (insert n (cdr lon)))) (else (cons n lon)) ) ) (define (ins-sort lon) (if (null? lon) '() (insert (car lon) (ins-sort (cdr lon))) ) ) • Precondition: second arg to insert ordered. • Postcondition: insert returns an ordered list. cs 3180(Prasad) L 14 Recur 21
Clojure Syntax (defn insert [n lon] (cond (empty? lon) (list n) (> n (first lon)) (cons (first lon) (insert n (rest lon))) : true (cons n lon)) ) ) (defn ins-sort [lon] (if (empty? lon) '() (insert (first lon) (ins-sort (rest lon))) ) ) • Precondition: second arg to insert ordered. • Postcondition: insert returns an ordered list. cs 3180(Prasad) L 14 Recur 22
Subset (uses OR and AND instead of IF) (define (subset? ss s) (or (null? ss) (and (member (car ss) s) (subset? (cdr ss) s) ) 1=> (subset? '(a b c) '(A p 1 C 2 B q r)) #t 2=> (subset? '(a b c) '(p)) #f cs 3180(Prasad) L 14 Recur 23
Anonymous functions and list membership test in Clojure > ( (fn [x y] (+ x y)) 25 30) 55 > ( #(+ %1 %2) 25 30) %2 55 > (some #(= 5 %) '(5 30)) true > (some #(= 5 %) '(15 30)) nil cs 3180(Prasad) L 14 Recur 24
Subset in Clojure (cf. case sensitive Scheme) (defn subset? [ss s] (or (empty? ss) (and (some #(= (first ss) %) s) (subset? (rest ss) s) ) > (subset? '() '(A p 1 C 2 B q r)) true > (subset? '(a b c) '(A p 1 C 2 B q r)) nil > (subset? '(a b c) '(p a c b)) true cs 3180(Prasad) L 14 Recur 25
Expression evaluation : A simple syntax directed translation expr -> x | y | -> (+ expr -> (if expr z expr) Write a recursive definition for a function ops that counts the number of “+”s. cs 3180(Prasad) L 14 Recur 26
(define (ops e) ; e is assumed to be a symbol or a list (cond ((symbol? e) 0) ((eq? (car e) '+) (+ 1 (ops (cadr e)) (ops (caddr e))) ) ((eq? (car e) 'if) (+ (ops (cadr e)) (ops (cadddr e)))) (else (display 'ILLEGAL)) ) ) cs 3180(Prasad) L 14 Recur 27
(defn third [x] (second (rest x))) (defn ops [e] ; Clojure code "e is assumed to be a symbol or a list" (cond (symbol? e) 0 (= (first e) '+) (+ 1 (ops (second e)) (ops (third e)) ) (= (first e) 'if) (+ (ops (second e)) (ops (third e)) (ops (last e))) true 'ILLEGAL )) cs 3180(Prasad) L 14 Recur 28
(Alternative Scheme syntax with member and case-construct (not equivalent)) (define (ops e) ; e is assumed to be a symbol or a list (if (member e '(x y z)) 0 (if (symbol? e) (display 'ILLEGAL) (case (car e) ((+) (+ 1 (ops (cadr e)) (ops (caddr e))) ) ((if) (+ (ops (cadr e)) (ops (cadddr e))) ) (else (display 'ILLEGAL))) ) )) cs 3180(Prasad) L 14 Recur 29
Examples (ops 'x) 0 (ops '(+ y z)) 1 (ops '(if x (+ y z) (+ x z))) 2 cs 3180(Prasad) L 14 Recur 30
(Alternative syntax in Clojure (not equivalent or robust)) (defn ops [e] ; e is assumed to legal (if (some #(= e %) '(x y z)) 0 (if (symbol? e) (println 'ILLEGAL) (case (first e) (+ 1 (ops (second e)) (ops (last e))) (if) (+ (ops (second e)) (ops (third e)) (ops (last e))) (println 'ILLEGAL))) ) ) cs 3180(Prasad) L 14 Recur 31