# SICP-2.2.4节练习

lispor posted @ Mar 18, 2011 01:18:03 AM in Scheme with tags SICP , 8955 阅读

```Define the procedure up-split used by corner-split. It is similar to right-split, except that it
switches the roles of below and beside.
```

```(define (up-split painter n)
(if (= n 0)
painter
(let ((smaller (up-split painter (- n 1))))
(below painter (beside smaller smaller)))))
```

```Right-split and up-split can be expressed as instances of a general splitting operation. Define a
procedure split with the property that evaluating
(define right-split (split beside below))
(define up-split (split below beside))
produces procedures right-split and up-split with the same behaviors as the ones already defined.
```

```(define (split origin-split smaller-split)
(lambda (painter n)
(if (= n 0)
painter
(let ((smaller ((split origin-split smaller-split) painter (- n 1))))
(origin-split painter (smaller-split smaller smaller))))))
```

```A two-dimensional vector v running from the origin to a point can be represented as a pair
consisting of an x-coordinate and a y-coordinate. Implement a data abstraction for vectors by giving
a constructor make-vect and corresponding selectors xcor-vect and ycor-vect. In terms of your
selectors and constructor, implement procedures add-vect, sub-vect, and scale-vect that perform the
operations vector addition, vector subtraction, and multiplying a vector by a scalar:
(x_1, y_1) + (x_2, y_2) = (x_1 + x_2, y_1 + y_2)
(x_1, y_1) - (x_2, y_2) = (x_1 - x_2, y_1 - y_2)
s * (x, y) = (sx, sy)```

```(define (make-vect x y)
(cons x y))

(define (xcor-vect vect)
(car vect))

(define (ycor-vect vect)
(cdr vect))

(define (add-vect vect1 vect2)
(let ((x1 (xcor-vect vect1))
(y1 (ycor-vect vect1))
(x2 (xcor-vect vect2))
(y2 (ycor-vect vect2)))
(make-vect (+ x1 x2)
(+ y1 y2))))

(define (sub-vect vect1 vect2)
(let ((x1 (xcor-vect vect1))
(y1 (ycor-vect vect1))
(x2 (xcor-vect vect2))
(y2 (ycor-vect vect2)))
(make-vect (- x1 x2)
(- y1 y2))))

(define (scale-vect scale vect)
(let ((x (xcor-vect vect))
(y (ycor-vect vect)))
(make-vect (* scale x)
(* scale y))))```

```Here are two possible constructors for frames:
(define (make-frame origin edge1 edge2)
(list origin edge1 edge2))
(define (make-frame origin edge1 edge2)
(cons origin (cons edge1 edge2)))
For each constructor supply the appropriate selectors to produce an implementation for frames.
```

```1.
(define (make-frame origin edge1 edge2)
(list origin edge1 edge2))

(define (origin-frame frame)
(car frame))

(define (edge1-frame frame)

(define (edge2-frame frame)

2.
(define (make-frame origin edge1 edge2)
(cons origin (cons edge1 edge2)))

(define (origin-frame frame)
(car frame))

(define (edge1-frame frame)

(define (edge2-frame frame)
(cddr frame))```

```A directed line segment in the plane can be represented as a pair of vectors—the vector running from
the origin to the start-point of the segment, and the vector running from the origin to the
end-point of the segment. Use your vector representation from Exercise 2-46 to define a
representation for segments with a constructor make-segment and selectors start-segment and
end-segment.```

```(define (make-segment start end)
(list start end))

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

(define (end-segment segment)
```

```Use segments->painter to define the following primitive painters:
a.The painter that draws the outline of the designated frame.
b.The painter that draws an “X” by connecting opposite corners of the frame.
c.The painter that draws a diamond shape by connecting the midpoints of the sides of the frame.
d.The wave painter.
```

```a.
(define (draw-frame-outline frame)
((segments->painter (list (make-segment (make-vect 0 0)
(make-vect 0 1))
(make-segment (make-vect 0 1)
(make-vect 1 1))
(make-segment (make-vect 1 1)
(make-vect 1 0))
(make-segment (make-vect 1 0)
(make-vect 0 0))))
frame))

b.
(define (draw-frame-X frame)
((segments->painter (list (make-segment (make-vect 0 0)
(make-vect 1 1))
(make-segment (make-vect 0 1)
(make-vect 1 0))))
frame))

c.
(define (draw-frame-diamond frame)
((segments->painter (list (make-segment (make-vect 0.5 0)
(make-vect 1 0.5))
(make-segment (make-vect 1 0.5)
(make-vect 0.5 1))
(make-segment (make-vect 0.5 1)
(make-vect 0 0.5))
(make-segment (make-vect 0 0.5)
(make-vect 0.5 0))))
frame))

d.
;; 60x60
(define wave-orgin-data '(((36 60) (40 50) (36 40) (42 40) (60 18))
((60 10) (36 30) (44 0))
((36 0)  (30 20) (24 0))
((16 0)  (24 30) (20 36) (10 30) (0 42))
((0 50)  (10 38) (20 40) (24 40) (20 50) (24 60))))

(define wave-vects-data (map (lambda (vs)
(map (lambda (xy)
(let ((x (car xy))
(make-vect (/ x 60.0) (/ y 60.0))))
vs))
wave-orgin-data))

(define wave-segments (fold-right append
'()
(map (lambda (vs)
(let loop ((xys vs))
(if (null? (cdr xys))
'()
(cons (make-segment (car xys) (cadr xys))
(loop (cdr xys))))))
wave-vects-data)))

(define (wave frame)
((segments->painter wave-segments)
frame))```

```Define the transformation flip-horiz, which flips painters horizontally, and transformations that
rotate painters counterclockwise by 180 degrees and 270 degrees.
```

```(define (flip-horiz painter)
(transform-painter painter
(make-vect 1.0 0.0)
(make-vect 0.0 0.0)
(make-vect 1.0 1.0)))

(define (rotate180 painter)
(transform-painter painter
(make-vect 1.0 1.0)
(make-vect 0.0 1.0)
(make-vect 1.0 0.0)))

(define (rotate270 painter)
(transform-painter painter
(make-vect 0.0 1.0)
(make-vect 0.0 0.0)
(make-vect 1.0 1.0)))
```

```Define the below operation for painters. Below takes two painters as arguments. The resulting
painter, given a frame, draws with the first painter in the bottom of the frame and with the second
painter in the top. Define below in two different ways—first by writing a procedure that is
analogous to the beside procedure given above, and again in terms of beside and suitable rotation
operations (from Exercise 2-50).```

```1.
(define (below painter1 painter2)
(let ((split-point (make-vect 0.0 0.5)))
(let ((paint-down (transform-painter painter1
(make-vect 0.0 0.0)
(make-vect 1.0 0.0)
split-point))
(paint-up (transform-painter painter2
split-point
(make-vect 1.0 0.5)
(make-vect 0.0 1.0))))
(lambda (frame)
(paint-down frame)
(paint-up frame)))))

2.
(define (below painter1 painter2)
(rotate90 (beside (rotate270 painter1) (rotate270 painter2))))
```

```Make changes to the square limit of wave shown in Figure 2-9 by working at each of the levels
described above. In particular:
a.Add some segments to the primitive wave painter of Exercise 2-49 (to add a smile, for example).
b.Change the pattern constructed by corner-split (for example, by using only one copy of the
up-split and right-split images instead of two).
c.Modify the version of square-limit that uses square-of-four so as to assemble the corners in a
different pattern. (For example, you might make the big Mr. Rogers look outward from each corner of
the square.)
```

```a.
;; 60x60
(define wave-orgin-data '(((36 60) (40 50) (36 40) (42 40) (60 18))
((60 10) (36 30) (44 0))
((36 0)  (30 20) (24 0))
((16 0)  (24 30) (20 36) (10 30) (0 42))
((0 50)  (10 38) (20 40) (24 40) (20 50) (24 60))
((25 50) (30 45) (35 50))))

(define wave-vects-data (map (lambda (vs)
(map (lambda (xy)
(let ((x (car xy))
(make-vect (/ x 60.0) (/ y 60.0))))
vs))
wave-orgin-data))

(define wave-segments (fold-right append
'()
(map (lambda (vs)
(let loop ((xys vs))
(if (null? (cdr xys))
'()
(cons (make-segment (car xys) (cadr xys))
(loop (cdr xys))))))
wave-vects-data)))

(define (wave frame)
((segments->painter wave-segments)
frame))

b.
(define (corner-split painter n)
(if (= n 0)
painter
(beside (below painter (up-split painter (- n 1)))
(below (right-split painter (- n 1)) (corner-split painter (- n 1))))))

c.
(define (square-limit painter n)
(let ((combine4 (square-of-four flip-vert rotate180
identity flip-horiz)))
(combine4 (corner-split painter n))))
```

Lox 说:
Mar 21, 2011 05:25:34 AM

wow! 宝库！

(输入验证码)
or Ctrl+Enter