1. A translation table is a list of pairs of characters. Within each pair, the character in the left field can be regarded as eligible for replacement or translation into the character in the right field.
Define a Scheme procedure uc-to-lc-table
that takes no
arguments and constructs and returns a translation table containing
twenty-six pairs, permitting the replacement of each upper-case letter of
the alphabet with the corresponding lower-case letter.
(define uc-to-lc-table (lambda () (let loop ((ch #\Z) (table '())) (if (char<? ch #\A) table (loop (predecessor ch) (cons (cons ch (char-downcase ch)) table)))))) (define predecessor (lambda (ch) (let ((ord (char->integer ch))) (if (zero? ord) (integer->char 255) (integer->char (- ord 1))))))2. Define a Scheme procedure
translate
that takes two
arguments, a string and a translation table, and returns a new string,
similar to the given string except that each of the characters that the
table makes eligible for translation has been replaced by the corresponding
character in the right field of the same pair in the translation table.
For instance, after exercise 1, the result of the call (translate
"DeForest Kelley" (uc-to-lc-table))
should be "deforest
kelley"
. (Hint: look at the entry for the assv
procedure in section 6.3 of the Revised(4) report.)
(define translate (lambda (str table) (let* ((len (string-length str)) (result (make-string len))) (let loop ((remaining len)) (if (zero? remaining) result (let* ((position (- remaining 1)) (ch (string-ref str position)) (mapping (assv ch table))) (string-set! result position (if mapping (cdr mapping) ch)) (loop position)))))))3. Define a Scheme procedure
write-in-reverse
that takes a
string as argument and writes it out backwards, last character first and
first character last, without changing the string. I don't care what the
procedure returns.
(define write-in-reverse (lambda (str) (let loop ((remaining (string-length str))) (if (not (zero? remaining)) (let ((position (- remaining 1))) (write-char (string-ref str position)) (loop position))))))4. Define a Scheme procedure that takes a string
str
as its
first argument and a natural number field
as its second
argument and prints str
, using exactly field
columns. If str
contains fewer than field
characters, enough spaces should be printed after it to pad it out to the
desired length; if str
contains more than field
characters, the extra characters at the right end of str
should be suppressed. I don't care what the procedure returns.
(define display-in-field (lambda (str field) (let ((len (string-length str))) (if (< field len) (display (substring str 0 field)) (begin (display str) (display (make-string (- field len) #\space)))))))5. Define a Scheme procedure
substrings
that constructs and
returns a list containing all of the distinct substrings of a given string,
in any order. For instance, given the string "alfalfa"
, the
procedure might return ("" "a" "al" "alf" "alfa" "alfal" "alfalf"
"alfalfa" "l" "lf" "lfa" "lfal" "lfalf" "lfalfa" "f" "fa" "fal" "falf"
"falfa")
.
(define substrings (lambda (str) (let outer ((aft (string-length str)) (result '())) (if (negative? aft) result (let inner ((fore aft) (result result)) (if (negative? fore) (outer (- aft 1) result) (let ((ss (substring str fore aft))) (inner (- fore 1) (if (member? ss result) result (cons ss result)))))))))) (define member? (lambda (obj ls) (and (not (null? ls)) (or (equal? obj (car ls)) (member obj (cdr ls))))))6. Define a Scheme predicate
every?
that takes two
arguments, a predicate and a list, and determines whether or not every
element of the given list satisfies the given predicate. If the list is
empty, every?
should return #t
. Also define the
dual predicate some?
that takes the same two arguments and
determines whether at least one element of the given list satisfies the
given predicate.
(define every? (lambda (pred? ls) (or (null? ls) (and (pred? (car ls)) (every? pred? (cdr ls)))))) (define some? (lambda (pred? ls) (and (not (null? ls)) (or (pred? (car ls)) (some? pred? (cdr ls))))))7. Define a Scheme procedure
map-over-structure
that, given a
procedure proc
and a numeric structure struct
, as
described in exercise set #4, builds and
returns a similar structure, except that each number in the given structure
has been replaced with the result of applying proc
to that
number. (So proc
must be a procedure of one argument that can
be applied to numbers.) For example, the value of the call
(map-over-structure sqrt '((25 . 36) . 81))
should be the
structure ((5 . 6) . 9)
.
(define map-over-structure (lambda (proc struct) (cond ((null? struct) '()) ((real? struct) (proc struct)) ((pair? struct) (cons (map-over-structure proc (car struct)) (map-over-structure proc (cdr struct)))) (else (error "map-over-structure: requires numeric structure")))))8. Define a Scheme procedure
try
that takes as arguments a
procedure proc
and a list ls
and applies
proc
to each of the elements of ls
in turn,
returning the first result that is not #f
, or #f
if all of the results are #f
.
(define try (lambda (proc ls) (and (not (null? ls)) (or (proc (car ls)) (try proc (cdr ls))))))9. Define a Scheme procedure
map-over-pairs
that returns a
list formed by applying a given procedure (of arity 2) to the left and
right fields of each pair on a given list of pairs. For instance, the
value of the call (map-over-pairs = '((4 . 3) (2 . 2) (5
. 7)))
should be (#f #t #f)
.
(define map-over-pairs (lambda (proc ls) (let loop ((rest ls) (result '())) (if (null? rest) (reverse result) (loop (cdr rest) (cons (proc (caar rest) (cdar rest)) result))))))10. Using the
read-char
procedure described in section 6.10.2
in the Revised(4) report, define a Scheme procedure
read-line
, of arity 0, that reads in all the characters up to
and including the next #\newline
character and returns a
string comprising all of those characters except the
#\newline
.
(define read-line (lambda () (let loop ((ch (read-char)) (ch-list '())) (if (or (eof-object? ch) (char=? ch #\newline)) (list->string (reverse ch-list)) (loop (read-char) (cons ch ch-list))))))