SICP. 2.2.4
2023-06-07 Wed
Exercise 2.44
Exercise:
Define the procedure
up-split
used bycorner-split
. It is similar toright-split
, except that it switches the roles of below and beside.
Answer:
(define (up-split painter n) (if (= n 0) painter (let ((smaller (right-split painter (- n 1)))) (below painter (beside smaller smaller)))))
Exercise 2.45
Exercise:
Right-split
andup-split
can be expressed as instances of a general splitting operation. Define a proceduresplit
with the property that evaluating(define right-split (split beside below)) (define up-split (split below beside))produces procedures
right-split
andup-split
with the same behaviors as the ones already defined.
Answer:
(define (split p1 p2) (lambda (painter n) (if (= n 0) painter (let ((smaller ((split p1 p2) painter (- n 1)))) (p1 painter (p2 smaller smaller))))))
Exercise 2.46
Exercise:
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 selectorsxcor-vect
andycor-vect
. In terms of your selectors and constructor, implement proceduresadd-vect
,sub-vect
, andscale-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 \cdot (x, y) = (sx, sy)\).
Answer:
(define (make-vect xcor ycor) (cons xcor ycor)) ;; alternatively: ;; (define make-vect cons) (define (xcor-vect vect) (car vect)) ;; alternatively: ;; (define xcor-vect car) (define (ycor-vect vect) (cdr vect)) ;; alternatively ;; (define ycor-vect cdr) (define (add-vect v1 v2) (make-vect (+ (xcor-vect v1) (xcor-vect v2)) (+ (ycor-vect v1) (ycor-vect v1)))) (define (sub-vect v1 v2) (make-vect (- (xcor-vect v1) (xcor-vect v2)) (- (ycor-vect v1) (ycor-vect v2)))) (define (scale-vect vect s) (make-vect (* (xcor-vect vect) s) (* (ycor-vect vect) s)))
Exercise 2.47
Exercise:
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:
(define (make-frame origin edge1 edge2) (list origin edge1 edge2)) (define (origin-frame frame) (car frame)) (define (edge1-frame frame) (car (cdr frame))) (define (edge2-frame frame) (car (cdr (cdr frame))))
Alternatively:
(define (make-frame origin edge1 edge2) (cons origin (cons edge1 edge2))) (define (origin-frame frame) (car frame)) (define (edge1-frame frame) (car (cdr frame))) (define (edge2-frame frame) (cdr (cdr frame)))
Exercise 2.48
Exercise:
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 selectorsstart-segment
andend-segment
.
Answer:
(define (make-segment vector1 vector2) (cons vector1 vector2)) (define (start-segment segment) (car segment)) (define (end-segment segment) (cdr segment))
Exercise 2.49
Exercise:
Use
segments->painter
to define the following primitive painters:
- The painter that draws the outline of the designated frame.
- The painter that draws an “X” by connecting opposite corners of the frame.
- The painter that draws a diamond shape by connecting the midpoints of the sides of the frame.
- The wave painter.
Answer:
;; Painter that draws the outline of the 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))))
;; Painter that draws an ``X'' (segments->painter (list (make-segment (make-vect 0 0) (make-vect 1 1)) (make-segment (make-vect 1 0) (make-vect 0 1))))
;; Painter that draws a diamond (segments->painter (list (make-segment (make-vect 0.5 0) (make-vect 0 0.5)) (make-segment (make-vect 0 0.5) (make-vect 0.5 1)) (make-segment (make-vect 0.5 1) (make-vect 1 0.5)) (make-segment (make-vect 1 0.5) (make-vect 0.5 0))))
Exercise 2.50
Exercise:
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-cc-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-cc-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
Exercise:
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. Definebelow
in two different ways—first by writing a procedure that is analogous to thebeside
procedure given above, and again in terms ofbeside
and suitable rotation operations (from Exercise 2.50).
Answer:
(define (below2 p1 p2) (let ((paint-below (transform-painter p1 (make-vect 0.0 0.0) (make-vect 1.0 0.0) (make-vect 0.0 0.5))) (paint-above (transform-painter p2 (make-vect 0.0 0.5) (make-vect 1.0 0.5) (make-vect 0.0 1.0)))) (lambda (frame) (paint-below frame) (paint-above frame)))) (paint (below2 einstein einstein))
(define (rotate-counterclock-90 painter) (transform-painter painter (make-vect 1.0 0.0) (make-vect 1.0 1.0) (make-vect 0.0 0.0))) (define (rotate-clock-90 painter) (transform-painter painter (make-vect 0.0 1.0) (make-vect 0.0 0.0) (make-vect 1.0 1.0))) (define (below3 p1 p2) (rotate-clock-90 (beside (rotate-counterclock-90 p1) (rotate-counterclock-90 p2)))) (paint (below3 einstein einstein))
Exercise 2.52
Exercise:
Make changes to the square limit of
wave
shown in Figure 2.9 by working at each of the levels described above. In particular:
- Add some segments to the primitive
wave
painter of Exercise 2.49 (to add a smile, for example).- Change the pattern constructed by
corner-split
(for example, by using only one copy of theup-split
andright-split
images instead of two).- Modify the version of
square-limit
that usessquare-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:
;; Change at the level of wave: replace wave with the einstein painter ;; available in Racket's SICP picture language. ;; Change at the level of corner split: swap right-split and up-split: (define (corner-split painter n) (if (= n 0) painter (let ((up (right-split painter (- n 1))) (right (up-split painter (- n 1)))) (let ((top-left (beside up up)) (bottom-right (below right right)) (corner (corner-split painter (- n 1)))) (beside (below painter top-left) (below bottom-right corner)))))) ;; Change at the level of square-limit: replace flip-vert with ;; flip-horiz: (define (square-limit painter n) (let ((quarter (corner-split painter n))) (let ((half (beside (flip-horiz quarter) quarter))) (below (flip-horiz half) half)))) (paint (square-limit einstein 3))