SICP-2.1.2节练习
练习 2.2 - 2.3
练习 2.2:
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)
练习 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?
我的解答:
(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