# SICP-2.1.2节练习

lispor posted @ Feb 24, 2011 03:20:42 PM in Scheme with tags SICP , 1364 阅读

```Consider the problem of representing line segments in a plane. Each segment is represented as a pair
of points: a starting point and an ending point. Define a constructor make-segment and selectors
start-segment and end-segment that define the representation of segments in terms of
points. Furthermore, a point can be represented as a pair of numbers: the x coordinate and the y
coordinate. Accordingly, specify a constructor make-point and selectors x-point and y-point that
define this representation. Finally, using your selectors and constructors, define a procedure
midpoint-segment that takes a line segment as argument and returns its midpoint (the point whose
coordinates are the average of the coordinates of the endpoints). To try your procedures, you'll
need a way to print points:
(define (print-point p)
(newline)
(display "(")
(display (x-point p))
(display ",")
(display (y-point p))
(display ")"))
```

```程序：
(define (make-point x y)
(cons x y))

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

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

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

(define (make-segment start end)
(cons start end))

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

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

(define (midpoint-segment segment)
(let ((start (start-segment segment))
(end (end-segment segment)))
(make-point (/ (+ (x-point start)
(x-point end))
2.0)
(/ (+ (y-point start)
(y-point end))
2.0))))

scheme@(guile-user)> (define p1 (make-point 3 6))
scheme@(guile-user)> (define p2 (make-point 4 3))
scheme@(guile-user)> (define s (make-segment p1 p2))
scheme@(guile-user)> (print-point (midpoint-segment s))
(3.5,4.5)```

```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?
```

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

(define (make-point x y)
(cons x y))

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

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

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

(define (distance-points point1 point2)
(let ((x1 (x-point point1))
(y1 (y-point point1))
(x2 (x-point point2))
(y2 (y-point point2)))
(sqrt (+ (square (- x2 x1))
(square (- y2 y1))))))

(define (make-segment start end)
(cons start end))

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

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

(define (length-segment segment)
(let ((start (start-segment segment))
(end (end-segment segment)))
(distance-points start end)))

(define (make-rect-1 base-segment height)
(cons base-segment height))

(define (width-rect-1 rect)
(let ((base-segment (car rect)))
(length-segment base-segment)))

(define (height-rect-1 rect)
(abs (cdr rect)))

(define (perimeter-rect-1 rect)
(let ((height (height-rect-1 rect))
(width (width-rect-1 rect)))
(* 2 (+ width height))))

(define (area-rect-1 rect)
(let ((height (height-rect-1 rect))
(width (width-rect-1 rect)))
(* width height)))

(define (make-rect-2 base-start base-end height)
(cons base-start
(cons base-end height)))

(define (width-rect-2 rect)
(let ((start (car rect))
(end (car (cdr rect))))
(distance-points  start end)))

(define (height-rect-2 rect)
(cdr (cdr rect)))

(define (perimeter-rect-2 rect)
(let ((width (width-rect-2 rect))
(height (height-rect-2 rect)))
(* 2 (+ width height))))

(define (area-rect-2 rect)
(let ((width (width-rect-2 rect))
(height (height-rect-2 rect)))
(* width height)))

(define (area-rect rect)
(if (pair? (car (car rect)))
(area-rect-1 rect)
(area-rect-2 rect)))

(define (perimeter-rect rect)
(if (pair? (car (car rect)))
(perimeter-rect-1 rect)
(perimeter-rect-2 rect)))

scheme@(guile-user)> (define p1 (make-point 3 6))
scheme@(guile-user)> (define p2 (make-point 3 9))
scheme@(guile-user)> (define s (make-segment p1 p2))
scheme@(guile-user)> (define rect1 (make-rect-1 s 6))
scheme@(guile-user)> (define rect2 (make-rect-2 p1 p2 6))
scheme@(guile-user)> (perimeter-rect rect1)
18.0
scheme@(guile-user)> (perimeter-rect rect2)
18.0
scheme@(guile-user)> (area-rect rect1)
18.0
scheme@(guile-user)> (area-rect rect2)
18.0``` (输入验证码)
or Ctrl+Enter