# weima learns to program

my attempt to do the exercises in sicp.

## Monday, July 7, 2008

### sicp exercise 2.3

;  Exercise 2.3.  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?

; square root
(define (sqrt-iter guess x)
(if (good-enough? guess x)
guess
(sqrt-iter (improve guess x) x)))

(define (improve guess x)
(average guess (/ x guess)))

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

(define (square x) (* x x))

(define (good-enough? guess x)
(< (abs (- (square guess) x)) 0.001))

(define (sqrt x)
(sqrt-iter 1.0 x))

; printing
(define (print-segment s)
(display "(")
(print-point (start-point s))
(display ",")
(print-point (end-point s))
(display ")"))

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

; Abstraction: line segment
(define (make-segment start end)(cons start end))

(define (start-point segment)(car segment))

(define (end-point segment)(cdr segment))

(define (length-segment segment)
(let ((y-point-start (y-point (start-point segment)))
(x-point-start (x-point (start-point segment)))
(y-point-end   (y-point (end-point segment)))
(x-point-end   (x-point (end-point segment))))
(cond ((= y-point-start y-point-end )
(abs (- x-point-start x-point-end )))
((= x-point-start x-point-end )
(abs (- y-point-start y-point-end )))
(else (sqrt (+ (square (- y-point-end y-point-start))
(square (- x-point-end x-point-start))))))))

; Abstraction: point
(define (make-point x y) (cons x y))

(define (x-point p)(car p))

(define (y-point p)(cdr p))

; Abstraction barrier:  get-segment-1 and get-segment-2
(define (perimeter rect)
(* 2 (+ (length-segment (get-segment-1 rect)) (length-segment (get-segment-2 rect)))))

(define (area rect)
(* (length-segment (get-segment-1 rect)) (length-segment (get-segment-2 rect))))

#!
; Represntation 1: the rectangle is aligned with x and y axis. so only 2 points on x and y axis are enough to specify the full rectangle.
; x1,x2 are points on x axis. y1,y2 are points on y axis

(define (make-rect x1 x2 y1 y2)
(cons (cons y1 y2) (cons x1 x2)))

; (x2 y1),(x1 y1)
(define (get-segment-1 rect)
(make-segment (make-point (cddr rect) (caar rect)) (make-point (cadr rect) (caar rect))))

; (x1 y2),(x1 y1)
(define (get-segment-2 rect)

; testing the representation 1
(define myrect (make-rect 2 3 10 20))
(print-segment (get-segment-1 myrect)) (newline)
(display (length-segment (get-segment-1 myrect))) (newline)
(print-segment (get-segment-2 myrect)) (newline)
(display (length-segment (get-segment-2 myrect))) (newline)
(display (perimeter myrect)) (newline)
(display (area myrect)) (newline)
!#

;#!
; Representation 2: the rectangle is represented by 4 points in the plane, whose co-ordinates are input to rectangle constructor. assumption is that x2,y2 is in middle of x1,y1 and x3,y3. then specifying x4,y4 is redundant.

(define (make-rect x1 x2 x3 x4 y1 y2 y3 y4)
(cons (cons (cons x1 y1) (cons x2 y2)) (cons (cons x3 y3) (cons x4 y4))))

;(x1 y1),(x2 y2)
(define (get-segment-1 rect)
(make-segment (make-point (caaar rect) (cdaar rect)) (make-point (cadar rect) (cddar rect))))

;(x3 y3),(x2 y2)
(define (get-segment-2 rect)

; testing the representation 2
(define myrect (make-rect 3 0 4 7 0 4 7 3))
(print-segment (get-segment-1 myrect)) (newline)
(display (length-segment (get-segment-1 myrect))) (newline)
(print-segment (get-segment-2 myrect)) (newline)
(display (length-segment (get-segment-2 myrect))) (newline)
(display (perimeter myrect)) (newline)
(display (area myrect)) (newline)
;!#

; There are two representations of rectangle. Comment one representation at a time and run the program.
; Both representations work fine.