1. Define a Scheme procedure that computes and returns the standard deviation of any non-empty list of real numbers.
(define standard-deviation (lambda (ls) (let* ((n (length ls)) (mu (/ (sum ls) n))) (sqrt (/ (let loop ((rest ls) (total 0.0)) (if (null? rest) total (loop (cdr rest) (+ total (square (- (car rest) mu)))))) n))))) (define sum (lambda (ls) (let sum-it ((rest ls) (total 0.0)) (if (null? rest) total (sum-it (cdr rest) (+ total (car rest))))))) (define square (lambda (n) (* n n)))2. Define a Scheme procedure that takes two lists of symbols, equal in length, and determines the number of positions at which they contain different values. For instance, given the lists
(a b c e f g)
and (a b d e g h)
, the procedure should return 3. Use a named
let
-expression as the body of the procedure and ensure that it
computes the result by an iterative process.
(define differ (lambda (list-1 list-2) (let differ-it ((rest-1 list-1) (rest-2 list-2) (tally 0)) (if (null? rest-1) tally (differ-it (cdr rest-1) (cdr rest-2) (if (eq? (car rest-1) (car rest-2)) tally (+ tally 1)))))))3. Let's dress up the preceding exercise a little by making it a component of an experiment in short-term memory. Suppose that the symbols in the first list are random letters or nonsense syllables that the subject is supposed to memorize during a short exposure, and those in the second list are the subject's report of what she remembers from that exposure. The Scheme procedure is supposed to evaluate how well the response was remembered.
For this purpose, the Scheme procedure defined in exercise 2 does a poor job, since it imposes just as great a penalty for mispositioning a symbol as for forgetting it entirely and substituting a completely different symbol. The exercise is to propose a better scoring method and to implement it as a Scheme procedure.
The following procedure awards one point for each symbol that the subject provides anywhere in her list, but subtracts a small penalty if it is in the incorrect position, counting from the front of the list. (The penalty is the distance between the guessed position of the symbol and its correct position, divided by the full length of the list.)
(define score (lambda (correct guessed) (let score-it ((rest-correct correct) (rest-guessed guessed) (right 0) (inversions 0)) (cond ((or (null? rest-correct) (null? rest-guessed)) (- right (/ inversions (length correct)))) ((member? (car rest-correct) rest-guessed) (score-it (cdr rest-correct) (remove-1st (car rest-correct) rest-guessed) (+ right 1) (+ inversions (index (car rest-correct) rest-guessed)))) ((member? (car rest-guessed) rest-correct) (score-it (remove-1st (car rest-guessed) rest-correct) (cdr rest-guessed) (+ right 1) (+ inversions (index (car rest-guessed) rest-correct)))) (else (score-it (cdr rest-correct) (cdr rest-guessed) right inversions)))))) (define member? (lambda (obj ls) (and (not (null? ls)) (or (eq? obj (car ls)) (member? obj (cdr ls)))))) (define remove-1st (lambda (obj ls) (let loop ((rest ls) (so-far '())) (cond ((null? rest) (reverse so-far)) ((eq? obj (car rest)) (append (reverse so-far) (cdr rest))) (else (loop (cdr rest) (cons (car rest) so-far))))))) (define index (lambda (obj ls) (let loop ((rest ls) (so-far 0)) (cond ((null? rest) #f) ((eq? obj (car rest)) so-far) (else (loop (cdr rest) (+ so-far 1)))))))4. Define a Scheme procedure
shuffle
that takes two lists
as arguments and returns a single list, the elements of which are drawn
alternately from the two given lists as long as they both hold out, after
which the rest of the elements are the same as those of the longer of the
given lists. For instance, the value of the call (shuffle '(a b c d
e) '(x y z))
is (a x b y c z d e)
.
(define shuffle (lambda (list-1 list-2) (let shuffle-it ((rest-1 list-1) (rest-2 list-2) (shuffled '())) (cond ((null? rest-1) (append (reverse shuffled) rest-2)) ((null? rest-2) (append (reverse shuffled) rest-1)) (else (shuffle-it (cdr rest-1) (cdr rest-2) (cons (car rest-2) (cons (car rest-1) shuffled))))))))5. Define a Scheme procedure
merge
that takes two lists of
real numbers, both in ascending order, and returns a single list,
containing all the elements from both lists, also in ascending order.
(define merge (lambda (list-1 list-2) (let merge-it ((rest-1 list-1) (rest-2 list-2) (merged '())) (cond ((null? rest-1) (append (reverse merged) rest-2)) ((null? rest-2) (append (reverse merged) rest-1)) ((< (car rest-1) (car rest-2)) (merge-it (cdr rest-1) rest-2 (cons (car rest-1) merged))) (else (merge-it rest-1 (cdr rest-2) (cons (car rest-2) merged)))))))6. Suppose we represent a playing card as a pair in which the left field is one of the four symbols
spade
, heart
,
diamond
, club
and the right field is an integer
in the range from 1 (= ace) to 13 (= king). Define a Scheme predicate that
determines whether a given list of five cards, considered as a poker hand,
is a flush (that is, whether they are all of the same suit). Extend the
exercise, if you like, to include predicates that test for other
holdings.
(define flush? (lambda (poker-hand) (alike? car poker-hand))) (define alike? (lambda (op ls) (or (null? ls) (null? (cdr ls)) (let loop ((first (car ls)) (second (cadr ls)) (rest (cddr ls))) (and (eq? (op first) (op second)) (or (null? rest) (loop second (car rest) (cdr rest))))))))7. Using the
random
procedure in SLIB or in your preferred
Scheme implementation, define a Scheme procedure of arity zero that
constructs and returns a randomly dealt five-card poker hand. (It's a
little harder than it may look, since you can't construct each card
independently. If your procedure deals out a hand with two aces of spades
in it, it will be shot.)
8. The setting this time involves a word game in which each letter has a
particular numerical value:
a, e, i, l, n, o, r, s, t, u: 1 point
d, g: 2 points
b, c, m, p: 3 points
f, h, v, w, y: 4 points
k: 5 points
j, x: 8 points
q, z: 10 points
Define a Scheme procedure that takes any word and determines the total of
the values of its letters. (This is pretty easy if you represent a word as
a list of letters, so for a little more of a challenge you might want to
take this opportunity to become familiar with Scheme's string and character
types by supposing that the argument will be presented as a string.)
(define word-score (lambda (word) (let loop ((remaining (string-length word)) (score 0)) (if (zero? remaining) score (let ((position (- remaining 1))) (loop position (+ score (letter-score (string-ref word position))))))))) (define letter-score (lambda (letter) (case letter ((#\a #\e #\i #\l #\n #\o #\r #\s #\t #\u #\A #\E #\I #\L #\N #\O #\R #\S #\T #\U) 1) ((#\d #\g #\D #\G) 2) ((#\b #\c #\m #\p #\B #\C #\M #\P) 3) ((#\f #\h #\v #\w #\y #\F #\H #\V #\W #\Y) 4) ((#\k #\K) 5) ((#\j #\x #\J #\X) 8) ((#\q #\z #\Q #\Z) 10) (else 0))))9. Define a Scheme procedure that takes a list of pairs, each pair consisting of a symbol (either
male
or female
)
and a real number (representing a subject's reaction time on a particular
task), and returns a list of two pairs, one consisting of the symbol
male
and the mean reaction time of all the male subjects, the
other consisting of the symbol female
and the mean reaction
time of all the female subjects. If the given list of pairs contains no
data for a sex, the corresponding entry in the result should have the
symbol no-data
in its right field instead of a number.
(define means-by-sex (lambda (data) (let loop ((rest data) (male-sum 0.0) (female-sum 0.0) (male-tally 0) (female-tally 0)) (cond ((null? rest) (list (cons 'male (if (zero? male-tally) 'no-data (/ male-sum male-tally))) (cons 'female (if (zero? female-tally) 'no-data (/ female-sum female-tally))))) ((eq? (caar rest) 'male) (loop (cdr rest) (+ male-sum (cdar rest)) female-sum (+ male-tally 1) female-tally)) ((eq? (caar rest) 'female) (loop (cdr rest) male-sum (+ female-sum (cdar rest)) male-tally (+ female-tally 1)))))))10. Suppose we represent a point in the Cartesian plane by a pair of real numbers, the car representing the point's x-coordinate and the cdr its y coordinate. Suppose further that we represent a line segment by a pair of which the two fields are the two endpoints of the segment.
Define a Scheme predicate that takes two line segments, one horizontal (i.e., both of its endpoints have the same y-coordinate) and the other vertical, and determines whether they intersect (that is, whether they have at least one point in common).
(define intersecting? (lambda (horizontal vertical) (and (or (<= (caar horizontal) (caar vertical) (cadr horizontal)) (<= (cadr horizontal) (caar vertical) (caar horizontal))) (or (<= (cdar vertical) (cdar horizontal) (cddr vertical)) (<= (cddr vertical) (cdar horizonal))))))