divide and conquer exercise

23 downloads 682 Views 68KB Size Report
divide and conquer. Yves Lespérance. Adapted from P. Roosen-Runge. 2. COSC3401-05-10-06 exercise. Write a function (bracket l) that takes a non-empty flat ...
divide and conquer Yves Lespérance Adapted from P. Roosen-Runge

COSC3401-05-10-06

1

exercise Write a function (bracket l) that takes a non-empty flat list l and returns a fully left-bracketed version, e.g.: (bracket ’(a)) returns (a) (bracket ’(a b)) returns ((a) b) (bracket ’(a b c)) returns (((a) b) c)

COSC3401-05-10-06

2

bracket exercise solution (DEFUN bracket (l) (bracketh (REST l) (LIST (FIRST l)))) (DEFUN bracket_h (l acc) (COND ((NULL l) acc) (T (bracket_h (REST l) (LIST acc (FIRST l)))) ))

COSC3401-05-10-06

3

divide & conquer - the idea 

split argument into two roughly equal pieces 



recurse on each

standard example: merge sort (p. 101)

COSC3401-05-10-06

4

modularity and recursion 

modularization into functions is forced by our use of recursion 



(each "loop" needs a name)

structuring the program flows naturally from the structure of the data  split: ( … ... ) -> ((.. .. ) ( .. .. ) ….) 

merge: (.. .. ) ( .. .. ) -> (…….)

COSC3401-05-10-06

5

merge sort example 

naturally breaks into separate functions/modules:    

orderp defines the ordering split preprocesses the data to produce roughly equal sub-problems merge composes solutions of sub-problems into solution to original problem mergesort integrates all of these modules

COSC3401-05-10-06

6

mergesort (DEFUN mergesort (seq) (IF (OR (ENDP seq)(ENDP (REST seq))) seq (LET ( (pair (split seq)) ) (merge (mergesort (FIRST pair)) (mergesort (SECOND pair))) )))

COSC3401-05-10-06

7

a more readable split (DEFUN split (seq) (COND ((ENDP seq) ’( () () )) ((ENDP (REST seq)) (LIST seq ’())) (T (LET ( (pair (split (REST (REST seq)))) ) (LIST (CONS (FIRST seq)(FIRST pair)) (CONS (SECOND seq) (SECOND pair)) )))))

COSC3401-05-10-06

8

a more readable merge (DEFUN merger (pair) ; merge is built-in function in CLisp (LET ((fs (FIRST pair))(ss (SECOND pair))) (COND ((ENDP fs) ss) ((ENDP ss) fs) ((orderp (FIRST fs)(FIRST ss)) (CONS (FIRST fs)(merger (LIST (REST fs) ss)))) (T (CONS (FIRST ss)(merger (LIST fs (REST ss))) )) ))) Ordering is abstracted into defined function orderp

COSC3401-05-10-06

9

merger trace > (merger '((1 6) (2 3 3))) 1. Trace: (MERGER '((1 6) (2 3 3))) 2. Trace: (ORDERP '1 '2) 2. Trace: ORDERP ==> T 2. Trace: (MERGER '((6) (2 3 3))) 3. Trace: (ORDERP '6 '2) 3. Trace: ORDERP ==> NIL 3. Trace: (MERGER '((6) (3 3))) 4. Trace: (ORDERP '6 '3) 4. Trace: ORDERP ==> NIL

COSC3401-05-10-06

10

merger trace (cont.) 4. Trace: (MERGER '((6) (3))) 5. Trace: (ORDERP '6 '3) 5. Trace: ORDERP ==> NIL 5. Trace: (MERGER '((6) NIL)) 5. Trace: MERGER ==> (6) 4. Trace: MERGER ==> (3 6) 3. Trace: MERGER ==> (3 3 6) 2. Trace: MERGER ==> (2 3 3 6) 1. Trace: MERGER ==> (1 2 3 3 6) (1 2 3 3 6)

COSC3401-05-10-06

11

split trace > (split '(1 2 3 4 5)) 1. Trace: (SPLIT '(1 2 3 4 5)) 2. Trace: (SPLIT '(3 4 5)) 3. Trace: (SPLIT '(5)) 3. Trace: SPLIT ==> ((5) NIL) 2. Trace: SPLIT ==> ((3 5) (4)) 1. Trace: SPLIT ==> ((1 3 5) (2 4)) ((1 3 5) (2 4)) COSC3401-05-10-06

12

generalization through modules 

the comparison must be handled by a function (orderp arg1 arg2):  

automatically creates a generalization the ordering is independent of the algorithm

COSC3401-05-10-06

13

variations on split  

original split (p. 101) not tail-recursive split with helper (p. 103) is tailrecursive 



(DEFUN split (seq) (sph seq ’() ’()))

another version of this where we package both results into a pair 

(DEFUN split2 (seq) (sph2 seq ’( () ()))

COSC3401-05-10-06

14

helper sph2 (DEFUN sph2 (seq result) (COND ((ENDP seq) result) ((ENDP (REST seq)) (LIST (CONS (FIRST seq) (FIRST result)) (SECOND result))) (T (split2 (REST (REST seq)) ; reduce by two elements (LIST (CONS (FIRST seq) (FIRST result)) (CONS (SECOND seq) (SECOND result)))) )) )

(split '(a b c d e)) = ((e c a) (d b))

COSC3401-05-10-06

15

split2 trace (split2 '(1 2 3 4 5)) 1. Trace: (SPH2 '(1 2 3 4 5) ’(()())) 2. Trace: (SPH2 '(3 4 5) '((1) (2))) 3. Trace: (SPH2 '(5) '((3 1) (4 2))) 3. Trace: SPH2 ==> ((5 3 1) (4 2)) ; no further computation 2. Trace: SPH2 ==> ((5 3 1) (4 2)) 1. Trace: SPH2 ==> ((5 3 1) (4 2)) ((5 3 1) (4 2))

COSC3401-05-10-06

16

complexity of merge sort 



running time of merge sort is O(n log n) where n is the number of items to be sorted. Idea: recursion depth is log2 n and a linear amount of work is done at each level. much better than insertion sort and selection sort which are O(n2).

COSC3401-05-10-06

17

other examples of D & C    

binary search quicksort finding closest points in a set etc.

COSC3401-05-10-06

18

patterns aren’t universal 

not every recursive function can be optimized through tail recursion 



in general, function with several arguments are more difficult 



e.g. APPEND

no simple concept of reducing argument “size”

MAPCAR or REDUCE are often much easier than designing recursion COSC3401-05-10-06

19