1. Define a Scheme procedure quadratic
that takes three
arguments a
, b
, and c
, all real
numbers, and returns a list of the roots of the quadratic equation
ax^2 + bx + c = 0.
(define quadratic-roots (lambda (a b c) (cond ((not (zero? a)) (discard-duplicates (quadratic-formula a b c))) ((not (zero? b)) (list (/ (- c) b))) ((not (zero? c)) '()) (else (display "all numbers are roots") (newline))))) (define discard-duplicates (lambda (solutions) (if (= (car solutions) (cadr solutions)) (cdr solutions) solutions))) (define quadratic-formula (lambda (a b c) (list (/ (+ (- b) (discriminant a b c)) (* 2 a)) (/ (- (- b) (discriminant a b c)) (* 2 a))))) (define discriminant (lambda (a b c) (sqrt (- (square b) (* 4 a c))))) (define square (lambda (n) (* n n)))2. Define a Scheme procedure
subst
that takes three arguments
(two arbitrary values and a list) and returns a list just like the given
list except that every occurrence of the first value has been replaced with
the second value. For instance, the value of the call (subst 'c 'k
'(c o c o n u t))
should be (k o k o n u t)
.
(define subst (lambda (old new ls) (if (null? ls) '() (cons (if (equal? old (car ls)) new (car ls)) (subst old new (cdr ls))))))3. Define a Scheme procedure
list-segment
that takes three
arguments -- the first a list, the second a natural number no greater than
the length of the list, and the third a natural number no less than the
second argument but no greater than the length of the list -- and returns a
segment of the given list, starting after the number of elements indicated
by the second argument and stopping after the element indicated by the
third argument. For instance, the value of the call (list-segment
'(a b c d e f g) 3 5)
should be (d e)
-- the segment of
(a b c d e f g)
that starts after the third element and stops
at the fifth. If the second and third elements are equal,
list-segment
should return the empty list.
(define list-segment (lambda (ls start stop) (if (zero? start) (list-segment-helper ls stop) (list-segment (cdr ls) (sub1 start) (sub1 stop))))) (define list-segment-helper (lambda (ls stop) (if (zero? stop) '() (cons (car ls) (list-segment-helper (cdr ls) (sub1 stop)))))) (define sub1 (lambda (n) (- n 1)))4. Define a Scheme procedure
range-sum
that takes two integer
arguments and finds the sum of all the integers greater than or equal to
the first argument and less than or equal to the second. For instance, the
value of the call (range-sum 12 16)
should be 70
(that is, 12 + 13 + 14 + 15 + 16).
(define range-sum (lambda (start stop) (if (< stop start) 0 (+ start (range-sum (add1 start) stop))))) (define add1 (lambda (n) (+ n 1)))5. Let's define a numeric structure, recursively, as a value that is either the null object, or a real number, or a pair of numeric structures. Define a Scheme procedure that finds the sum of all the real numbers that occur anywhere inside a given numeric structure.
(define sum-of-structure (lambda (struct) (cond ((null? struct) 0) ((real? struct) struct) ((pair? struct) (+ (sum-of-structure (car struct)) (sum-of-structure (cdr struct)))) (else (error "sum-of-structure: argument not a numeric structure")))))6. Define a Scheme procedure that finds that greatest real number in a given numeric structure. (If the structure contains no real numbers -- for instance, if it is the null object -- the procedure should return
#f
.)
(define greatest-of-structure (lambda (struct) (cond ((null? struct) #f) ((real? struct) struct) ((pair? struct) (greater-if-number (greatest-of-structure (car struct)) (greatest-of-structure (cdr struct)))) (else (error "greatest-of-structure: argument not a numeric structure"))))) (define greater-if-number (lambda (val-1 val-2) (if val-1 (if val-2 (max val-1 val-2) val-1) val-2)))7. Similarly, let's define a symbolic structure as a value that is either the null object, or a symbol, or a pair of symbolic structures. Define a Scheme procedure
contents
that takes any symbolic
structure as its argument and returns a list of all the symbols that occur
anywhere inside that symbolic structure.
(define contents (lambda (struct) (cond ((null? struct) '()) ((symbol? struct) (list struct)) ((pair? struct) (append (contents (car struct)) (contents (cdr struct)))) (else (error "contents: argument not a symbolic structure")))))8. Here's an alternative definition of a symbolic structure: a value that is either a symbol or a list of symbolic structures. Is this definition equivalent to the one proposed in the preceding exercise? Will your definition of
contents
still work for symbolic structures in
the new sense? If not, how would you revise it?
The proposed new definition is more restrictive than the one used in the
preceding exercise, since, for instance, the pair (a . b)
counts as a symbolic structure under the old definition but not under the
new one (it is neither a symbol nor a list). But everything that is a
symbolic structure under the new definition was already covered under the
old definition. (Since a list of symbolic structures is either the null
object or a pair with a symbolic structure in its left field and a list of
symbolic structures in its right field, the proposition follows by
mathematical induction on the length of the list.) It is not necessary to
change the definition of contents
.
9. Define a Scheme procedure sum
that yields the result
described in exercise 3.1 on page 81 of the text, but obtains that result
by an iterative process (as described in section 4.5).
(define sum-it (lambda (ls) (sum-it-helper ls 0))) (define sum-it-helper (lambda (ls acc) (if (null? ls) acc (sum-it-helper (cdr ls) (+ (car ls) acc)))))10. Define the
iota
procedure (exercise set #2, number 7) so
that it obtains its result by an iterative process.
(define iota-it (lambda (n) (iota-it-helper n '()))) (define iota-it-helper (lambda (n so-far) (if (zero? n) so-far (iota-it-helper (sub1 n) (cons (sub1 n) so-far)))))