;;; File:
;;; searching.scm
;;; Author:
;;; Samuel A. Rebelsky
;;; Version:
;;; 1.0 of February 2004
;;; Summary:
;;; Values and procedures for exploring searching.
;;; Contents:
;;; cartoons: A vector of two-element lists (protagonist sidekick)
;;; binary-search: The traditional binary-search procedure.
;;; Name:
;;; cartoons
;;; Type:
;;; Ordered vector of two-element lists
;;; Value:
;;; Each two-element list contains a protagonist and a sidekick
;;; (in that order).
;;; The vector is ordered by protagonist.
(define cartoons
(vector
(list "Ash" "Misty")
(list "Asterix" "Obelix")
(list "Bart Simpson" "Milhouse Van Houten")
(list "Batman" "Robin")
(list "Bullwinkle" "Rocky")
(list "Dexter" "Didi")
(list "Dick Dastardly" "Muttley")
(list "Duck Dodgers" "Porky Pig")
(list "Fred" "Barney")
(list "Josie" "The Pussycats")
(list "Peabody" "Sherman")
(list "Peter Griffin" "Brian")
(list "Quick Draw McGraw" "Baba Looey")
(list "Ren" "Stimpy")
(list "Rocko" "Heffer")
(list "Scooby Doo" "Scrappy Doo")
(list "Scooby Doo" "Shaggy")
(list "Secret Squirrel" "Morocco Mole")
(list "Spongebob" "Patrick")
(list "Tennessee Tuxedo" "Chumley")
(list "Yogi" "Booboo")
(list "Yu-Gi-Oh" "Joey")
))
;;; 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 the key of a data item.
;;; comes-before?, a binary predicate that tells us whether or not
;;; one key may precede another.
;;; Produces:
;;; match, a number.
;;; Preconditions:
;;; The vector is "sorted". That is,
;;; (comes-before? (get-key (vector-ref vec i))
;;; (get-key (vector-ref vec (+ i 1))))
;;; holds for all reasonable i.
;;; The comes-before? procedure can be applied to all pairs of keys
;;; in the vector (and to the supplied key)
;;; The comes-before? procedure is transitive. That is, if
;;; (comes-before? a b) and (comes-before? b c) then it must
;;; be that (comes-before? a c).
;;; The comes-before? procedure excludes equal values. If a does not
;;; come before b and b does not come before a, then a equals b.
;;; Simlarly, if a equals b, then neither comes before the other.
;;; Postconditions:
;;; If vector contains no element whose key matches key, match is -1.
;;; If vec contains an element whose key equals key, match is the
;;; index of one such value. That is, key is
;;; (get-key (vector-ref vec match))
(define binary-search
(lambda (key vec get-key comes-before?)
; 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)))
(display (list 'searching lower-bound upper-bound))
(newline)
(display (list 'midpoint midpoint middle-key))
(newline)
(cond ((comes-before? key middle-key)
(search-portion lower-bound (- midpoint 1)))
((comes-before? middle-key key)
(search-portion (+ midpoint 1) upper-bound))
(else midpoint)))
-1))))