;;; File: ;;; search.ss ;;; Author: ;;; Samuel A. Rebelsky ;;; Version: ;;; 1.2 of April 2001 ;;; Summary: ;;; A collection of procedures that can be used for searching. ;;; Contents: ;;; History: ;;; Tuesday, 14 November 2000 [v 1.0] ;;; Created ;;; Wednesday, 15 November 2000 [v 1.1] ;;; Added some sample lists. ;;; Wednesday, 18 April 2001 [v 1.2] ;;; Updated the sample lists to reflect this semester's enrollments. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Values ;;; Name: ;;; lastnames ;;; Type: ;;; Vector of strings ;;; Contents: ;;; Last names of the CSC151 2001S Students (define lastnames (vector "Armah" "Chaturvedi" "DeVilder" "Eilert" "Farrow" "Fynn" "Gamboa" "Heinz" "Hensing" "Hernandez" "Hodgman" "Ipatova" "Kase" "Likarish" "Makinen" "Mapes" "McClelland" "Nuss-Warren" "Ofori-Addo" "Pekarscaya" "Pervaiz" "Porter" "Schrieber" "Shaw" "Sheikh" "Smith" "Tiwari" "Walker" "Waymouth" "Yeboah")) ;;; Name: ;;; students ;;; Type: ;;; Vector of student records ;;; Each record has form (lastname firstname box email gradyear major) ;;; Everything in that record is a string. ;;; Values: ;;; Basic info on CSC151 2001S (define students (vector (list "Armah" "Kabenla" "16-81" "ARMAHKE" "2004" "UND") (list "Chaturvedi" "Samarth" "03-14" "CHATURVE" "2004" "UND") (list "DeVilder" "Anna" "04-06" "DEVILDER" "2003" "UND") (list "Eilert" "Sara" "04-49" "EILERTS" "2004" "UND") (list "Farrow" "Brad" "04-68" "FARROW" "2004" "UND") (list "Fynn" "Papa Tony" "05-17" "FYNNAP" "2004" "UND") (list "Gamboa" "Matthew" "00-00" "GAMBOA" "2006" "UND") (list "Heinz" "Patty" "06-20" "HEINZPL" "2004" "UND") (list "Hensing" "Roger" "00-00" "HENSING" "1900" "MAT" ) (list "Hernandez" "Alex" "17-28" "HERNANDA" "2001" "PSY-RUS") (list "Hodgman" "Amanda" "06-36" "HODGMAN" "2004" "UND") (list "Ipatova" "Natalia" "06-89" "IPATOVAN" "2002" "EXCH") (list "Kase" "Aaron" "17-82" "KASEA" "2004" "UND") (list "Likarish" "Peter" "07-69" "LIKARISH" "2004" "UND") (list "Makinen" "Laura" "08-06" "MAKINEN" "2002" "REL") (list "Mapes" "Marie" "10-68" "MAPES" "2001" "CHM") (list "McClelland" "Katherine" "00-00" "MCCLELLA" "1900" "REL") (list "Nuss-Warren" "Sarah" "10-55" "NUSSWARR" "2002" "PHY") (list "Ofori-Addo" "Daniel" "10-26" "OFORIADD" "2004" "UND") (list "Pekarscaya" "Katya" "10-66" "PEKARSCA" "2002" "EXCH") (list "Pervaiz" "Ammar" "10-82" "PERVAIZA" "2004" "UND") (list "Porter" "Audrey" "11-50" "PORTER" "2002" "MAT") (list "Schrieber" "Greg" "12-41" "SCHRIEBE" "2002" "POL") (list "Shaw" "Jim" "12-40" "SHAW" "2003" "UND") (list "Sheikh" "Muhammad" "12-75" "SHEIKHMA" "2004" "UND") (list "Smith" "Tony" "13-28" "SMITHG" "2001" "PHI") (list "Tiwari" "Ananta" "14-10" "TIWARIAN" "2004" "UND") (list "Walker" "Xylina" "15-09" "WALKERXH" "2004" "UND") (list "Waymouth" "Rob" "15-42" "WAYMOUTH" "2004" "UND") (list "Yeboah" "George" "15-85" "YEBOAHGD" "2004" "UND"))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Procedures ;;; Procedure: ;;; linear-search-list ;;; Parameters: ;;; lst, a list ;;; pred?, predicate ;;; Purpose: ;;; Searches the list for a value that matches ;;; the predicate. ;;; Produces: ;;; A matching value, if one exists. ;;; #f, otherwise. ;;; Preconditions: ;;; The first parameter is a list. ;;; The second parameter is a unary predicate. ;;; Postconditions: ;;; If the procedure returns #f, no element of the ;;; list matches the predicate. ;;; If the procedure returns some other value, v, then ;;; (1) (pred? v) returns #t and (2) v is in lst. (define linear-search-list (lambda (pred? lst) (cond ; If the list is empty, no values match the predicate. ((null? lst) #f) ; If the predicate holds on the first value, use that one. ((pred? (car lst)) (car lst)) ; Otherwise, look at the rest of the list (else (linear-search-list pred? (cdr lst)))))) ;;; Procedure: ;;; linear-search-vector ;;; Parameters: ;;; vec, a vector ;;; pred?, predicate ;;; Purpose: ;;; Searches the vector for a value that matches ;;; the predicate. ;;; Produces: ;;; The index of the matching value, if there is one. ;;; #f, otherwise. ;;; Preconditions: ;;; The first parameter is a vector. ;;; The second parameter is a unary predicate. ;;; Postconditions: ;;; If the procedure returns #f, no element of the ;;; vector matches the predicate. ;;; If the procedure returns some other value, i, then ;;; (pred? (vector-ref vec i)) returns #t. (define linear-search-vector (lambda (pred? vec) ; Grab the length of the vector so that we don't have to ; keep recomputing it. (let ((len (vector-length vec))) ; Helper: Keeps track of the position we're looking at. (let kernel ((position 0)) ; Start at position 0 (cond ; If we've run out of elements, give up. ((= position len) #f) ; If the current element matches, use it. ((pred? (vector-ref vec position)) position) ; Otherwise, look in the rest of the vector. (else (kernel (+ position 1)))))))) ;;; Procedure: ;;; search-list-for-keyed-value ;;; Parameters: ;;; key, a key to search for. ;;; values, a list of compound values. ;;; get-key, a procedure that extracts a key from a compound value. ;;; Purpose: ;;; Finds a member of the list that has a matching key. ;;; Produces: ;;; A matching value, if found. ;;; #f, otherwise. ;;; Preconditions: ;;; The get-key procedure can be applied to each element of values. ;;; Postconditions: ;;; If the procedure returns #f, there is no value for which ;;; (equal? key (get-key val)) ;;; holds. Otherwise, returns some value for which that holds. (define search-list-for-keyed-value (lambda (key values get-key) (linear-search-list (lambda (val) (equal? key (get-key val))) values))) ;;; Procedure: ;;; binary-search ;;; Parameters: ;;; key, a key we're looking for ;;; vec, a vector to search ;;; get-key, a procedure of one parameter that, given a data item, ;;; returns thek ey of that data item. ;;; less-equal?, a binary predicate that tells us whether or not ;;; one key is less-than-or-equal-to another. ;;; Produces: ;;; The index of a value with key sought, if found. ;;; #f, otherwise. ;;; Preconditions: ;;; The vector is "sorted. That is, ;;; (less-equal? (get-key (vector-ref vec i)) ;;; (get-key (vector-ref vec (+ i 1)))) ;;; holds for all reasonable i. ;;; The less-equal? procedure can be applied to all pairs of keys ;;; in the vector (and to the supplied ot key) ;;; Postconditions: ;;; If the procedure returns #f, no element of the ;;; vector matches the predicate. ;;; If the procedure returns some other value, i, then ;;; the key of (vector-ref vec i) is equal to key. (define binary-search (lambda (key vec get-key less-equal?) ; Search a portion of the vector from lower-bound to upper-bound (let search-portion ((lower-bound 0) (upper-bound (- (vector-length vec) 1))) (if (<= lower-bound upper-bound) (let* ((midpoint (quotient (+ lower-bound upper-bound) 2)) (middle-element (vector-ref vec midpoint)) (middle-key (get-key middle-element))) (cond ((not (less-equal? middle-key key)) (search-portion lower-bound (- midpoint 1))) ((not (less-equal? key middle-key)) (search-portion (+ midpoint 1) upper-bound)) (else midpoint))) #f))))