- (define (up-split painter n)
- (if (= n 0)
- painter
- (let ((up (up-split painter (- n 1))))
- (below painter (beside up up)))))
Exercise 2.45. 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.
Answer:
- (define (split orig-placer split-placer)
- (lambda (painter n)
- (if (= n 0)
- painter
- (let ((smaller ((split orig-placer split-placer) painter (- n 1))))
- (orig-placer smaller (split-placer smaller smaller))))))
Exercise 2.46. 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:

Answer:
- (define (make-vect x-cord y-cord)
- (cons x-cord y-cord))
- (define (xcor-vect vector)
- (car vector))
- (define (ycor-vect vector)
- (cdr vector))
- (define (add-vect v1 v2)
- (make-vect (+ (xcor-vect v1) (xcor-vect v2))
- (+ (ycor-vect v1) (ycor-vect v2))))
- (define (sub-vect v1 v2)
- (make-vect (- (xcor-vect v1) (xcor-vect v2))
- (- (ycor-vect v1) (ycor-vect v2))))
- (define (scale-vect s v)
- (make-vect (* s (xcor-vect v))
- (* s (ycor-vect v))))
Exercise 2.47. 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.
Answer:
- ;; Option 1 and selectors
- (define (make-frame origin edge1 edge2)
- (list origin edge1 edge2))
- (define (origin-frame frame)
- (car frame))
- (define (edge1-frame frame)
- (cadr frame))
- (define (edge2-frame frame)
- (caddr frame))
- ;; Option 2 and selectors
- (define (make-frame origin edge1 edge2)
- (cons origin (cons edge1 edge2)))
- (define (origin-frame frame)
- (car frame))
- (define (edge1-frame frame)
- (cadr frame))
- (define (edge2-frame frame)
- (cddr frame))
Exercise 2.48. 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.
Answer:
- (define (make-segment start-point-vector end-point-vector)
- (cons start-point-vector end-point-vector))
- (define (start-segment segment)
- (car segment))
- (define (end-segment segment)
- (cdr segment))
Exercise 2.49. 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.
Answer: a. The painter that draws the outline of the designated frame. This is done by connecting the four corners of the frame. Translated to the unit frame the corners are the points
(0, 0)
, (1, 0)
, (0, 1)
and (1, 1)
.
- (define outline-segments
- (let ((origin (make-vect 0.0 0.0))
- (one-zero (make-vect 1.0 0.0))
- (zero-one (make-vect 0.0 1.0))
- (one-one (make-vect 1.0 1.0)))
- (list
- (make-segment origin zero-one)
- (make-segment origin one-zero)
- (make-segment one-zero one-one)
- (make-segment one-one zero-one))))
- (define outline-painter (segments->painter outline-segments))
b. Painting an x is accomplished by connecting opposite corners of the frame. This means drawing a line connecting
(0, 0)
to (1, 1)
and (0, 1)
to (1, 0)
respectively.
- (define diagonal-segments
- (let ((origin (make-vect 0.0 0.0))
- (one-zero (make-vect 1.0 0.0))
- (zero-one (make-vect 0.0 1.0))
- (one-one (make-vect 1.0 1.0)))
- (list
- (make-segment origin one-one)
- (make-segment zero-one one-zero))))
- (define x-painter (segments->painter diagonal-segments))
c. A diamond shape is created by connecting the midpoints of the sides of the unit square.
- (define midpoint-segments
- (let ((m1 (make-vect 0.5 0.0))
- (m2 (make-vect 1.0 0.5))
- (m3 (make-vect 0.5 1.0))
- (m4 (make-vect 0.0 0.5)))
- (list
- (make-segment m1 m2)
- (make-segment m2 m3)
- (make-segment m3 m4)
- (make-segment m4 m1))))
- (define diamond-painter (segments->painter midpoint-segments))
d. I'll skip the wave painter. Too many line segments!
Exercise 2.50. Define the transformation flip-horiz, which flips painters horizontally, and transformations that rotate painters counterclockwise by 180 degrees and 270 degrees.
Answer:
- (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 (rotate-ccw-180 painter)
- (transform-painter painter
- (make-vect 1.0 1.0)
- (make-vect 0.0 1.0)
- (make-vect 1.0 0.0)))
- (define (rotate-ccw-270 painter)
- (transform-painter painter
- (make-vect 0.0 1.0)
- (make-vect 0.0 0.0)
- (make-vect 1.0 1.0)))
Exercise 2.51. 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).
Answer:
- ;; below - analogous to beside
- (define (below painter-bottom painter-top)
- (let ((split-point (make-vect 0 0.5)))
- (let ((paint-top
- (transform-painter painter-top
- split-point
- (make-vect 1.0 0.5)
- (make-vect 0.0 1.0)))
- (paint-bottom
- (transform-painter painter-bottom
- (make-vect 0.0 0.0)
- (make-vect 1.0 0.0)
- split-point)))
- (lambda (frame)
- (paint-top frame)
- (paint-bottom frame)))))
- ;; below in terms of beside and rotation operations from Exercise 2.50
- (define (below painter-bottom painter-top)
- (lambda (frame)
- (rotate-ccw-90
- (beside (rotate-ccw-270 painter-bottom)
- (rotate-ccw-270 painter-top)))
- frame))
Exercise 2.52. 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.)
Answer: I am skipping the smiley part.
- ;; b. change pattern used by corner-split
- (define (corner-split painter n)
- (if (= n 0)
- painter
- (let ((up (up-split painter (- n 1)))
- (right (right-split painter (- n 1))))
- (let ((corner (corner-split (painter (- n 1)))))
- (beside (below painter up)
- (below right corner))))))
- ;; c. modify square-limit
- (define (square-limit painter n)
- (let ((quarter (corner-split painter n)))
- (let ((half (beside quarter (flip-horiz quarter))))
- (below (flip-vert half) half))))
No comments:
Post a Comment