;; The NORM procedure computes the square root of the sum of the squares
;; of the elements of a given vector.
(define norm
(lambda (vec)
;; Make sure that VEC is a vector of numbers.
(if (not ((vector-of number?) vec))
(error 'norm "The argument must be a vector of numbers"))
;; Traverse the vector (from right to left, in this case), squaring
;; each element and adding the result to a running total. After all
;; of the elements have been processed, extract and return the square
;; root of the running total.
(let loop ((remaining (vector-length vec))
(total 0))
(if (zero? remaining)
(sqrt total)
(let ((next (- remaining 1)))
(loop next (+ total (square (vector-ref vec next)))))))))
;; The VECTOR-OF procedure takes a predicate PRED as argument and returns a
;; procedure that takes any object as argument and determines whether it is
;; a vector in which PRED correctly characterizes every element. (If it is
;; a vector that has no elements, the procedure returned by VECTOR-OF
;; returns #T, on the theory that PRED is ``vacuously true'' of the
;; vector's elements.)
(define vector-of
(lambda (pred)
(lambda (obj)
(and (vector? obj)
(let loop ((remaining (vector-length obj)))
(or (zero? remaining)
(let ((next (- remaining 1)))
(and (pred (vector-ref obj next))
(loop next)))))))))
;; The SQUARE procedure takes any number and returns the result of
;; multiplying it by itself.
(define square
(lambda (n)
;; Make sure that N is a number.
(if (not (number? n))
(error 'square "The argument must be a number"))
;; Square it.
(* n n)))
;; Given a vector VEC of real numbers, the CUMULATIVE-TOTALS constructs and
;; returns another vector of the same length, with each position of the new
;; vector containing the sum of the elements of VEC up to and including the
;; corresponding position.
(define cumulative-totals
(lambda (vec)
;; Make sure that VEC is a vector of real numbers.
(if (not ((vector-of real?) vec))
(error 'cumulative-totals
"The argument must be a vector of real numbers"))
;; Allocate a RESULT vector to hold the cumulative totals.
(let* ((len (vector-length vec))
(result (make-vector len)))
;; Traverse both vectors from left to right, adding each element
;; of VEC to the running total and storing the new value of that
;; total in RESULT.
(let loop ((position 0)
(total 0))
(if (= position len)
result
(let ((new-total (+ total (vector-ref vec position))))
(vector-set! result position new-total)
(loop (+ position 1) new-total)))))))
;; The PARTITION procedure takes two arguments, the first, VEC, a vector of
;; strings and the second, PIVOT, a string, and rearranges the elements of
;; VEC so that every string that lexicographically precedes or equals PIVOT
;; is in a lower-numbered position than any of the strings that
;; lexicographically follows PIVOT. It returns the number of elements of
;; VEC that lexicographicallly precede or equal PIVOT.
(define partition
(lambda (vec pivot)
;; Make sure that VEC is a vector of strings.
(if (not ((vector-of string?) vec))
(error 'partition
"The first argument must be a vector of strings"))
;; Make sure that PIVOT is a string.
(if (not (string? pivot))
(error 'partition "The second argument must be a string"))
;; Traverse the vector from left to right, keeping a tally of the
;; elements that lexicographically precede or equal the pivot. Each
;; time such an element is encountered, swap it into the position
;; indicated by the current value of the tally and then increment
;; the tally by one. When all of the elements of the vector have
;; been examined, all of the elements that lexicographically precede
;; or equal the pivot will have been swapped into positions less
;; than the value of the tally, and all those in positions equal to
;; or greater than the tally will lexicographically follow the
;; pivot. So the postcondition will have been met, and it remains
;; only to return the value of the tally.
(let ((len (vector-length vec)))
(let loop ((position 0)
(tally 0))
(cond ((= position len) tally)
((string<=? (vector-ref vec position) pivot)
(let ((temp (vector-ref vec position)))
(vector-set! vec position (vector-ref vec tally))
(vector-set! vec tally temp))
(loop (+ position 1) (+ tally 1)))
(else (loop (+ position 1) tally)))))))
This document is available on the World Wide Web as
http://www.math.grin.edu/courses/Scheme/solutions-4.html