Home > Notes > Books > Notes and Solutions from Structure and Interpretation of Computer Programs

2.1 Introduction to Data Abstraction

Exercise 2.1

It handles a 0 denominator weirdly but I'll fix that when I need to.

(define (make-rat n d)
(define remainder mod)
(define (gcd a b)
(if (= b 0)
    a
    (gcd b (remainder a b))))
(define (get-numerator n d)
(if (positive? (* n d)) (abs n) (- (abs n))))
(let ((g (abs (gcd n d))))
(cons (/ (get-numerator n d) g)
      (/ (abs d) g))))

Exercise 2.2

(define (average x y) (/ (+ x y) 2))

(define (make-segment s e) (cons s e))
(define (start-segment s) (car s))
(define (end-segment s) (cdr s))

(define (make-point x y) (cons x y))
(define (x-point p) (car p))
(define (y-point p) (cdr p))

(define (midpoint-segment s)
(make-point 
(average (x-point (start-segment s))
          (x-point (end-segment s)))
(average (y-point (start-segment s))
          (y-point (end-segment s)))))

(define (print-point p)
(display "(")
(display (x-point p))
(display ",")
(display (y-point p))
(display ")")
(newline))

Exercise 2.3

(define (make-rect p1 p2)
(cons p1 p2))

(define (rect-helper x-op y-op r)
(make-point (x-op (x-point (car r)) 
                (x-point (cdr r)))
          (y-op (y-point (car r))
                (y-point (cdr r)))))

(define (top-right r) (rect-helper max max r))
(define (top-left r) (rect-helper min max r))
(define (bottom-left r) (rect-helper min min r))
(define (bottom-right r) (rect-helper max min r))

(define (length r)
(- (x-point (top-right r))
  (x-point (top-left r))))

(define (height r)
(- (y-point (top-right r))
  (y-point (bottom-right r))))

(define (perimeter r)
(+ (* 2 (length r)) (* 2 (height r))))

(define (area r)
(* (length r) (height r)))

Here I'm representing a rect internally as a pair of points, but I could switch my construtor to represent it as 4 points, or as 2 or 4 line segments, without having to change the area or perimeter definitions. But I won't.

Exercise 2.4

(define (cdr z)
(z (lambda (p q) q)))

Exercise 2.5

(define (factor n f)
(define (fact-rec n result)
(if (or (= n 1) (not (= (mod n f) 0)))
    result
    (fact-rec (/ n f) (+ result 1))))
(fact-rec n 0))

(define (cons a b) (* (expt 2 a) (expt 3 b)))
(define (car c) (factor c 2))
(define (cdr c) (factor c 3))

Exercise 2.6

This is one to revisit, I'll defer to the helpful solution here for now.

Exercise 2.7

(define (make-interval a b) (cons a b))
(define (upper-bound i) (cdr i))
(define (lower-bound i) (car i))

Exercise 2.8

(define (sub-interval x y)
(make-interval (- (lower-bound x) (upper-bound y))
              (- (upper-bound x) (lower-bound y))))

Exercise 2.9

This is another proof-style question I didn't complete. See Codology's solution here.

Exercise 2.10

(define (div-interval x y)
(if (< (* (upper-bound y) (lower-bound y)) 0) 
  (print "Can't divide by an interval that spans zero!" y)
  (mul-interval x (make-interval 
                  (/ 1.0 (upper-bound y))
                  (/ 1.0 (lower-bound y))))))

Exercise 2.11

I'm not too engaged by this extended exercise and I had a feeling this question would involve a lot of work without teaching me too much Lisp. A quick skim of the wiki seems to confirm. I'm going to skip this one as well for now. Someday I'll come back and do these ones I missed.

Exercise 2.12

(define (make-center-percent c p)
(let ((width (* c (/ p 100))))
(make-center-width c width)))

(define (percent i)
(* (/ (width i) (center i)) 100))

Exercise 2.13

Some quick tests make it looks like in the case of small intervals you can just add the percentage tolerance to approximate the percentage tolerance of the product of the intervals. I don't have a formal proof of this.

Exercise 2.14

Exercise 2.15

Exercise 2.16

I am bored of this example so I'm moving on. I skimmed a solution to these 3 and I think I understand the concept being taught. I'll come back through these notes sometime and complete them.

Previous Next