SICP Exercise 2.3
Question
Implement a representation for rectangles in a plane. (Hint: You may want to make use of exercise 2.2.) In terms of your constructors and selectors, create procedures that compute the perimeter and the area of a given rectangle. Now implement a different representation for rectangles.
Can you design your system with suitable abstraction barriers, so that the same perimeter and area procedures will work using either representation?
Answer
We are going to be making use of the wishful thinking technique
described by the authors for this exercise. In this spirit, let
us start by setting up the actual area
and perimeter
functions. We can concern ourselves with the actual
implementations later.
(define (area r)
(* (length-seg (get-a r)) (length-seg (get-b r))))
(define (perimeter r)
(* (+ (length-seg (get-a r)) (length-seg (get-b r))) 2))
(define (get-a rect) (car rect))
(define (get-b rect) (cdr rect))
Add in a few helper functions (constructors and selectors for segments and points as well as a function to calculate the length of a segment):
(define (make-seg p1 p2) (cons p1 p2))
(define (get-start seg) (car seg))
(define (get-end seg) (cdr seg))
(define (make-point x y) (cons x y))
(define (get-x pnt) (car pnt))
(define (get-y pnt) (cdr pnt))
(define (square x) (* x x))
(define (length-seg seg)
(let ((x1 (get-x (get-start seg)))
(x2 (get-x (get-end seg)))
(y1 (get-y (get-start seg)))
(y2 (get-y (get-end seg))))
(sqrt (+ (square (- x2 x1)) (square (- y2 y1))))))
Then, we can set up the first rectangle implementation. Here, I am choosing to represent a rectangle as three points, like the following graphic:
(define (make-rect-1 p1 p2 p3)
(let ((seg1 (make-seg p1 p2))
(seg2 (make-seg p1 p3)))
(cons seg1 seg2)))
Then, another implementation, this time using only two points (the diagonals) to describe the rectangle:
(define (make-rect-2 p1 p2)
(let ((x1 (get-x p1))
(x2 (get-x p2))
(y1 (get-y p1))
(y2 (get-y p2)))
(cons (make-seg p1 (cons x1 y2)) (make-seg p1 (cons x2 y1)))))
Set up some test points and two rectangles with different representations (note that they describe the same rectangle):
(define p1 (make-point 0 0))
(define p2 (make-point 0 2))
(define p3 (make-point 3 0))
(define p4 (make-point 3 2))
(define rect1 (make-rect-1 p1 p2 p3))
(define rect2 (make-rect-2 p1 p4))
And run some tests:
(area rect1)
(perimeter rect1)
(newline)
(area rect2)
(perimeter rect2)
Results:
6
10
6
10