1 Vectors, binary search, and sorting
2 We know about lists O(n) time to get the n-th item. Consecutive cons cell are not necessarily consecutive in memory
3 Alternatively, use indirect addressing Put items consecutively in memory Knowing the base we can calculate the address of the n-th item ! so we can access the n-th item in O(1) time -- random access What did we loose ? Cannot easily add elements in the middle base
4 Indirect addressing in scheme -- via vectors (define v (vector 3 '(2 3 b (4 5)) 'anna)) v ==> #(3 (2 3 b (4 5)) anna) (vector-length v) ==> 3 (car (vector-ref v 1)) ==> 2 (vector-set! v 2 'foo) v ==> #(3 (2 3 b (4 5)) foo) (define vv (make-vector 4 '())) vv ==> #(() () () ()) (vector-set! vv 2 (vector-ref v 2)) vv ==> #(() () foo ()) (define ll (list vv v)) (vector? (car ll)) ==> #t
5 Indirect addressing in scheme -- via vectors (vector... ) ; create a vector from the 0 or more elements (make-vector k) ; create a vector of length k (make-vector k init) ; same, but each element is initialized to init (vector-length vec) ; returns the length of the vector vec (vector-ref vec k) ; returns the element of vec with index k ; k should be between 0 and length-1 (vector-set! vec k elt) ; stores elt in the element k of the ; vector vec. k should be between 0 and length-1 (vector? obj) ; returns true if obj is a vector, false otherwise
6 Binary search The algorithm needs random access The input vector must be sorted Compare x to the middle element of the vector If x is smaller then x must be in the first half of the vector If x is larger then x must be in the second half of the vector If x is equal, we found it
7 Binary search (Cont.) (define (bin-search vec x) (define (search left right) (if (> left right) nil (let* ((mid (average left right)) (mid-item (vector-ref vec mid))) (cond ((= x mid-item) mid) ((< x mid-item) (search left (- mid 1))) (else (search (+ mid 1) right)))))) (search 0 (- (vector-length vec) 1))) (define (average x y) (round (/ (+ x y) 2)))
8 Binary search (Cont.) With one comparison, reduce search space to half its size Run time is (log n)
9 Sorting Collection of data elements, which may be compound Each data element has a key, from ordered domain. (In our example there will be just keys). We would like to order the elements according to the keys, in increasing order
10 Bubble sort The algorithm compares neighbors, and exchanges them when they are out of order Go through elements from last to first, performing this on each pair of neighbors, the smallest element will reach its correct position as first. Make an additional pass, reaching the second element only, and so on, until all elements are in place
11 Bubble sort
12 Implementation of Bubble sort (define (bubble-sort vec) (define n (vector-length vec)) (define (iter i) (define (bubble j) (if (>= j i) (let ((prev (vector-ref vec (- j 1))) (cur (vector-ref vec j))) (cond ((> prev cur) (vector-set! vec (- j 1) cur) (vector-set! vec j prev))) (bubble (- j 1))))) (cond ((< i n) (bubble (- n 1)) (iter (+ i 1))))) (iter 1))
13 Bubble sort Number of comparisons is (n-1) + (n-2) = n*(n-1)/2 Number of exchanges: worst case, same as number of comparisons; best case 0. In any case, the running time is (n 2 )
14 Quicksort The algorithm chooses some element, called pivot. Splits the elements into three groups: smaller equal, and larger than the pivot. Recursively sort the smaller and the larger groups independently
15 Quicksort (Cont.) (define (quicksort l) (if (null? l) nil (let ((pivot (car l))) (let ((low (filter (lambda (x) (< x pivot)) l)) (high (filter (lambda (x) (> x pivot)) l)) (same (filter (lambda (x) (= x pivot)) l))) (append (append (quicksort low) same) (quicksort high))))))
16 Quicksort -- brief analysis T(n) = cn + T(m) + T(n-m-1) where m is the number of elements smaller than the pivot (for simplicity assume the keys are all different). n m n-m-1 cn c(n-1) c(n-2)
17 Quicksort -- brief analysis Best case, when the algorithm partitions the elements into two equal size groups at each stage. Worst case is when m=0 (or m=n-1), giving T(n) = cn + c(n-1) + c(n-2) + + c = cn(n+1)/2 so T(n) = (n 2 ) T(n) cn + c(n-1) + c(n-2) + + c = cn(n+1)/2 so T(n) = O(n 2 )
18 Other sorting algorithms Mergesort -- in homework Heapsort -- hopefully in the course about data structures
19 The metacircular evaluator
20 The metacircular evaluator Parts of an interpreter Start growing the evaluator slowly Arithmetic calculator Add names Conditionals and if Store procedures in the environment Environment as explicit parameter Defining new procedures
21 Why do we need an interpreter? Abstractions let us bury details and focus on use of modules to solve large systems Need to unwind abstractions at execution time to deduce meaning Have seen such a process – Environment Model Now want to describe that process as a procedure
22 Stages of an interpreter "(average 4 (+ 5 5))" (average4( +55 ) ) 4 symbol average 5 symbol Lexical analyzer Parser Evaluator Environment Printer "7" input to each stage
23 Role of each part of the interpreter Lexical analyzer break up input string into "words" called tokens Parser convert linear sequence of tokens to a tree like diagramming sentences in elementary school also convert self-evaluating tokens to their internal values –#f is converted to the internal false value Evaluator follow language rules to convert parse tree to a value read and modify the environment as needed Printer convert value to human-readable output string
24 Our goal of the next few lectures Implement an interpreter for a programming language Only write evaluator and environment use scheme's reader for lexical analysis and parsing use scheme's printer for output to do this, our language must look like scheme Start with a simple calculator for arithmetic Progressively add scheme features until we have the metacircular evaluator as in the book
25 1. Arithmetic calculator Want to evaluate arithmetic expressions of two arguments, like: (+ 24 (+ 5 6))
26 (define (tag-check e sym) (and (pair? e) (eq? (car e) sym))) (define (sum? e) (tag-check e ‘+)) (define (eval exp) (cond ((number? exp) exp) ((sum? exp) (eval-sum exp)) (else (error "unknown expression " exp)))) (define (eval-sum exp) (+ (eval (cadr exp)) (eval (caddr exp)))) (eval '(+ 24 (+ 5 6)))
27 We are just walking through a tree … (eval ) sum? checks the tag
28 We are just walking through a tree … (eval-sum ) (+ (eval 24) (eval )) (+ (eval 5) (eval 6))
29 1. Things to observe cond determines the expression type no work to do on numbers scheme's reader has already done the work it converts a sequence of characters like "24" to an internal binary representation of the number 24 eval-sum recursively calls eval on both argument expressions
30 2. Names Extend the calculator to store intermediate results as named values (define x (+ 4 5)) store result as x (+ x 2) use that result Store bindings between names and values in a table
31 2. Names ( define (define? exp) (tag-check exp 'define)) (define (eval exp) (cond ((number? exp) exp) ((symbol? exp) (lookup exp)) ((sum? exp) (eval-sum exp)) ((define? exp) (eval-define exp)) (else (error "unknown expression " exp)))) (define environment (make-frame ‘() ‘())) (define (lookup name) (lookup-variable-value name environment)) (define (eval-define exp) (let ((name (cadr exp)) (defined-to-be (eval (caddr exp)))) (add-binding-to-frame! name defined-to-be environment) ‘undefined))
32 (define (make-frame variables values) (cons variables values)) (define (lookup-variable-value var frame) (define (scan vars vals) (cond ((null? vars) (error "Unbound variable" var)) ((eq? var (car vars)) (car vals)) (else (scan (cdr vars) (cdr vals))))) (let ((vars (car frame)) (vals (cdr frame))) (scan vars vals))) (define (add-binding-to-frame! var val frame) (set-car! frame (cons var (car frame))) (set-cdr! frame (cons val (cdr frame))))
33 The environment is a single frame list of values list of variables frame xy4 5