;; countup function: old code that uses helper function
; (define (countup n)
; (cond
; [(= n 1) (cons 1 empty)]
; [else
; (countup-helper 1 n)]))
; (define (countup-helper start end)
; (cond
; [(= start end) (cons end empty)]
; [else
; (cons start
; (countup-helper (add1 start) end))]))
;; new countup - uses local definition of helper
(define (countup n)
(local
((define (countup-helper start end)
(cond
[(= start end) (cons end empty)]
[else
(cons start
(countup-helper (add1 start) end))])))
(countup-helper 1 n)))
;; (countup 20)
;; simple minded findmax of a list of numbers
;; very inefficient - roughly n*(n+1)/2 comparisons
;; where we only need n.
;;
(define (findmax alon)
(cond
[(empty? (rest alon)) (first alon)]
[(> (first alon) (findmax (rest alon))) (first alon)]
[ else (findmax (rest alon))]))
;; here is a better (more efficient) definition
;;
;; the advantage is that each time findmax2 is called,
;; it computes (findmax2 (rest alon)) at most once.
;; (sets a variable to the value returned by findmax2).
(define (findmax2 alon)
(cond
[(empty? (rest alon)) (first alon)]
[ else
(local
((define restmax (findmax2 (rest alon))))
(cond
[(> (first alon) restmax) (first alon)]
[ else restmax]))]))
(findmax '(3 12 7 4 1 ))
(findmax2 '(3 12 7 4 1 ))
;;
;; sort consumes a list and produces a list
;;
;; (sort alon) will create a list with the same elements
;; as alon, but in ascending order.
;;
;; usage: (sort '(1 3 12 4 8))
;;
;; uses local definitions for a findmin function,
;; a function that removes a value from a list,
;; and uses a variable to record the smallest
;; value on the list (instead of finding this
;; out twice
(define (sort alon)
(cond
;; base cases
[(empty? alon) empty]
[(empty? (rest alon)) alon]
[else
;; we have at least two numbers in the list.
(local
;; findmin finds the minimum number in a list of numbers
((define (findmin alon)
(cond
[(empty? (rest alon)) (first alon)]
[ else
(local
((define restmin (findmin (rest alon))))
(cond
[(< (first alon) restmin) (first alon)]
[ else restmin]))]))
;; remove-element consumes a number and a list and returns a list.
;; creates a list with all the elements in alon, except that
;; a single instance of x is removed. Order is preserved.
(define (remove-element x alon)
(cond
[(= x (first alon)) (rest alon)]
[else
(cons (first alon) (remove-element x (rest alon)))]))
;; find the smallest element in the list
(define smallest (findmin alon)))
;; simply put the smallest at the beginning, and
;; sort the remaining element.
(cons smallest (sort (remove-element smallest alon))))]))
(sort '(1 3 12 7 6 2 4))
;; tree building
;;
;; want to create a binary search tree from a list of numbers
;; (in any order?)
;;
;; binary search tree node:
;;
;; a bst node is either empty, or a bsnode
;;
;; a bsnode is a structure with num, left and right,
;; where num is a number, left and right are bsnodes.
;;
(define-struct bsnode (num left right))
;;
;; make-bst creates a binary search tree from a list of numbers.
;;
;; make-bst consumes a list and produces a binary search tree.
;;
;; (make-bst alon) creates a binary search tree using bsnode
;; structures. The search tree holds the elements of the list
;; of numbers alon.
;;
;; general strategy:
;; 1. sort the list
;; 2. pick middle element of sorted list
;; for the root of the tree
;; 3. build a bsnode with num from step 2.
;; left node being a binary search tree
;; made from all elements less than num,
;; and right being a binary search tree made
;; from all elements greater than num.
(define (make-bst alon)
(local
(
;; select an item from a list given it's position in the list.
(define (select-elem-at-pos pos alist)
(cond
[(= 0 pos) (first alist)]
[else (select-elem-at-pos (sub1 pos) (rest alist))]))
;; pick middle element from ordered list - just uses
;; length/2 as index of the element we want.
(define (pick-middle olon)
(select-elem-at-pos (floor (/ (length olon) 2)) olon))
;; sublist consumes a value, a relational operator and a list
;; and produces a list.
;;
;; (sublist val op alist) uses the relation operator
;; op to filter the elements in alist according to thier
;; relationship with val.
;;
;; if (op element val) is true, then element is one of the
;; items in the list produced.
;;
;; For example, if alist is a list of numbers, op is <
;; and val is 7, sublist will return all the elements of
;; alist that are less than 7.
;;
;; usage: (sublist 7 < '(4 8 3 9 12))
(define (sublist val op alist)
(cond
[(empty? alist) empty]
[(op (first alist) val)
(cons (first alist) (sublist val op (rest alist)))]
[ else
(sublist val op (rest alist))]))
;; uses sublist to get a list of all elements in alist
;; that are less than val
(define (sublist-lessthan val alist)
(sublist val < alist))
;; uses sublist to get a list of all elements in alist
;; that are less than val
(define (sublist-greaterthan val alist)
(sublist val > alist))
)
;; beginning of the body of the local
(cond
[(empty? alon) empty ] ;; no elements - no tree
[ else
(local
((define sorted (sort alon)) ;; sort the list
(define middle (pick-middle sorted))) ;; pick middle element
;; make a bst
(make-bsnode
middle
;; left is a bst containing all elements less than middle
(make-bst (sublist-lessthan middle sorted))
;; right is a bst containing all elements greater than middle
(make-bst (sublist-greaterthan middle sorted))))])))
;; test code
;;(make-bst '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))