






Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
Handout 31 for cs107, spring 2008, discussing mergesort and function mapping in scheme. It includes the mergesort algorithm, prefix-of-list function, and the use of map and apply. Also, it covers the concept of depth in lists and flattening lists using map, apply, and append.
Typology: Study notes
1 / 12
This page cannot be seen from the preview
Don't miss anything!







CS107 Handout 31 Spring 2008 May 19, 2008
Handout written by Jerry Cain.
;; Function: sorted? ;; ----------------- ;; Returns true if and only if the specified list of numbers is sorted ;; from low to high. In other words, it confirms that all neighboring ;; pairs of integers respect the <= predicate. ;; (define (sorted? numbers) (or (< (length numbers) 2) (and (<= (car numbers) (cadr numbers)) (sorted? (cdr numbers)))))
#|kawa:2|# (sorted? '(1 3 4 5)) #t #|kawa:3|# (sorted? '(1 4 5 3)) #f #|kawa:4|# (sorted? '()) #t #|kawa:5|# (sorted? '(3.4)) #t #|kawa:6|# (sorted? '(1/3 4/5 7/2 12/5)) #f #|kawa:7|# (sorted? '("Alice" "Bobby" "Carol")) Invalid parameter, was: gnu.lists.FString java.lang.ClassCastException: gnu.lists.FString at gnu.kawa.functions.NumberCompare.apply2(NumberCompare.java:118) at gnu.kawa.functions.NumberCompare.apply2(NumberCompare.java:113) at atInteractiveLevel$19.isSorted(scheme-examples.scm:268) at atInteractiveLevel$19.apply1(scheme-examples.scm:266) at gnu.expr.ModuleMethod.apply1(ModuleMethod.java:191) at gnu.expr.ModuleMethod.apply(ModuleMethod.java:162) at gnu.mapping.CallContext.runUntilDone(CallContext.java:251) at gnu.expr.ModuleExp.evalModule(ModuleExp.java:222) at kawa.Shell.run(Shell.java:229) at kawa.Shell.run(Shell.java:172) at kawa.Shell.run(Shell.java:159) at kawa.repl.main(repl.java:744)
(define (string-sequence-sorted? strings) (or (< (length strings) 2) (and (<= (car strings) (cadr strings)) (string-sequence-sorted? (cdr strings))))) #|kawa:8|# (string-sequence-sorted? '("Alice" "Bobby" "Carol")) #t
;; Function: sorted? ;; ----------------- ;; Returns true if and only if the specified list is sorted ;; according to the specified predicate function. In other words, ;; true is returned if and only if each neighboring pair respects ;; the provided comparison function. ;; (define (sorted? sequence comp) (or (< (length sequence) 2) (and (comp (car sequence) (cadr sequence)) (sorted? (cdr sequence) comp)))) #|kawa:2|# (sorted? '(1 4 5 7 8 10 14) <) #t #|kawa:3|# (sorted? '(8.5 4.3 2.0 0.4 - 1.3 - 5.5) >) #t #|kawa:4|# (sorted? '(8.5 4.3 2.0 0.4 - 7.3 - 5.5) >) #f #|kawa:5|# (sorted? '("apple" "banana" "banana" "cherry") string<=?) #t #|kawa:6|# (define (list-length<? ls1 ls2) (< (length ls1) (length ls2))) #|kawa:7|# (sorted? '((1) ("a" 'b) ((#t) 4.5 (10/3 8+7i))) list-length<?) #t
;; Function: merge ;; --------------- ;; Takes the two lists, each of which is assumed to be sorted ;; according to the specified comparator function, and synthesizes ;; an fresh list which is the sorted merge of the incoming two. ;; ;; If one of the lists is empty, then merge can just return the ;; other one. If not, then the specified comp is used to determine ;; which of the two cars deserves to be at the front. Recursion (what else?) ;; is then used to generate the merge of everything else, and the winning ;; car is consed to the front of it. ;; (define (merge list1 list2 comp) (cond ((null? list1) list2) ((null? list2) list1) ((comp (car list1) (car list2)) (cons (car list1) (merge (cdr list1) list2 comp))) (else (cons (car list2) (merge list1 (cdr list2) comp)))))
;; Function: prefix-of-list ;; ------------------------ ;; Accepts a list and returns a new list with just the ;; first k elements. If k is greater than the original ;; list length, the entire list is replicated. If k is ;; negative, then don't except it to work. :) ;; (define (prefix-of-list ls k) (if (or (zero? k) (null? ls)) '() (cons (car ls) (prefix-of-list (cdr ls) (- k 1)))))
;; Function: mergesort ;; ------------------- ;; Sorts the incoming list called ls so that all neighboring ;; pairs of the final list respect the specified comparator function. ;; ;; mergesort works by taking the unsorted list, generating copies of ;; the front half and the back half, recursively sorting them, and then ;; merging the two. Classic mergesort. ;; ;; The reverse call is a bit hokey, but it brings the back half to ;; the front so that our prefix-of-list function has access to the ;; back-end elements. The fact that the elements are in the reverse ;; of the original order is immaterial, since we don't care about ;; the original order—just the order after it's been sorted. ;; (define (mergesort ls comp) (if (<= (length ls) 1) ls (let ((front-length (quotient (length ls) 2)) (back-length (- (length ls) (quotient (length ls) 2)))) (merge (mergesort (prefix-of-list ls front-length) comp) (mergesort (prefix-of-list (reverse ls) back-length) comp) comp))))
#|kawa:2|# (mergesort '(1 5 3 2 5 6 3 4 5 9 2) <) (1 2 2 3 3 4 5 5 5 6 9) #|kawa:3|# (mergesort '(1/2 1/3 1/4 1/6 1/7 1/8 1/ #|(---:4|# 2/3 2/5 2/7 2/9 3/4 3/5 3/7 3/8 4/5 4/7 4/9) >) (4/5 3/4 2/3 3/5 4/7 1/2 4/9 3/7 2/5 3/8 1/3 2/7 1/4 2/9 1/6 1/7 1/8 1/9) #|kawa:5|# (mergesort '("a" "b" "c" "d" "e" "z" "y" "x" "w") string>?) (z y x w e d c b a)
#|kawa:2|# (map append '((a b c) (x y z)) '((d e) (p d q))) ((a b c d e) (x y z p d q)) #|kawa:3|# (map + '(10 200 3000) '(7 8 9)) (17 208 3009) #|kawa:4|# (map cons '("Haley" "Sarah" "Bond [arrogant pause]") #|(---:5|# '(("Joel" "Osment") ("Jessica" "Parker") ("James" "Bond"))) ((Haley Joel Osment) (Sarah Jessica Parker) (Bond [arrogant pause] James Bond)) #|kawa:6|#
#|kawa:15|# (map list '(1 2 3) '(10 20 30) '(100 200 300) '(1000 2000 3000)) ((1 10 100 1000) (2 20 200 2000) (3 30 300 3000 ))
;; Function: unary-map ;; ------------------- ;; We pretend that the map function doesn't exist, and we write ;; our own. As you can see, it isn't all that difficult to get ;; a unary version of map working. ;; (define (unary-map fn seq) (if (null? seq) '() (cons (fn (car seq)) (unary-map fn (cdr seq))))) #|kawa:2|# (unary-map list '(a "b" 4.5 (#f #t #t))) ((a) (b) (4.5) ((#f #t #t))) #|kawa:3|# (unary-map / '(5 6 99 121)) (1/5 1/6 1/99 1/121)
#|kawa:2|# (apply + '(1 2 3 4)) 10 #|kawa:3|# (sqrt (apply + (map * '(3 4) '(3 4))))
;; Function: average ;; ----------------- ;; Quick, clean way to compute the average of a set of numbers without ;; using any exposed car-cdr recursion. This is the canonical example ;; illustrating why apply belongs in a functional language. ;; (define (average num-list) (/ (apply + num-list) (length num-list))) #|kawa:2|# (average '(3 5 9 11 3)) 31/ #|kawa:3|# (average '(99998 99999 100000 100001 100002)) 100000 #|kawa:4|# (average '(3.4 8.3 2.7 6.6))
;; Function: flatten-list ;; ---------------------- ;; Flattens a list just like the original flatten does, but ;; it uses map, apply, and append instead of exposed car-cdr recursion. ;; (define (flatten-list ls) (cond ((null? ls) '()) ((not (list? ls)) (list ls)) (else (apply append (map flatten-list ls))))) #|kawa:2|# (flatten-list '(1 2 (3) 4)) (1 2 3 4) #|kawa:3|# (flatten '(this (list (also has) substance) ((((([deep]))))))) (this list also has substance [deep])
#|kawa:2|# (translate '(7 4 2 - 4 8 1) 50) (57 54 52 46 58 51) #|kawa:3|# (translate '(1 2 3 4 5 6) 1/8) (9/8 17/8 25/8 33/8 41/8 49/8)
;; Function: translate ;; ------------------- ;; Takes the specified list and the specified delta and generates ;; a new list where every element of the original is shifted by the ;; specified delta. ;; (define (translate numbers delta) (define (shift number) (+ number delta)) (map shift numbers))
;; Function: translate ;; ------------------- ;; Takes the specified list and the specified delta and generates ;; a new list where every element of the original is shifted by the ;; specified delta. This version uses the lambda construct ;; to define a nameless function in place. ;; (define (translate numbers delta) (map (lambda (number) (+ number delta)) numbers))