Note: this wiki is now retired and will no longer be updated!

The static final versions of the pages are left as a convenience for readers. Note that meta-pages such as "discussion," "history," etc., will not work.

SICP exercise 2.52

From Drewiki
Jump to: navigation, search
Comment The solution for this exercise requires the use of the PLT Scheme DrScheme graphical environment. Ensure the DrScheme language is set to Module before running the program.
Comment The picture language implemented by the PLT Scheme SICP picture package is slightly different than the picture language described in the text. The PLT package lacks the wave and rogers pictures; the solution provided here will use the diagonal-shading and einstein pictures provided by the PLT package instead. Also, painters in the PLT picture package don't know how to draw themselves. In order to draw a painter in the DrScheme graphical environment, use the paint procedure: it takes a single argument, the painter to draw, e.g.,

(paint einstein)

The (require ...) expression at the beginning of the program automatically loads the PLT picture package from the DrScheme web site. It may not work if you're attempting to run the program from behind a proxy or outbound firewall.

For more information on the PLT SICP picture package, see here.

Contents

Problem

Make changes to the square limit of wave shown in figure 2.9 of the text 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.)

Solution

All 3 parts of the exercise are straightforward.

Solution, part A

Here's the original wave from exercise 2.49.

#lang scheme
(require (planet "sicp.ss" ("soegaard" "sicp.plt" 2 1)))
 
(define nil '())
 
(define (connect vect-list)
  (define (iter segment-list remaining)
    (if (null? (cdr remaining))
        (reverse segment-list)
        (iter (cons (make-segment (car remaining)
                                  (cadr remaining))
                    segment-list)
              (cdr remaining))))
  (iter nil vect-list))
 
(define (wave frame)
  ((segments->painter (append (connect (list (make-vect 0.4  0.0)
                                             (make-vect 0.5  0.33)
                                             (make-vect 0.6  0.0))) ;inside legs
                              (connect (list (make-vect 0.25 0.0)
                                             (make-vect 0.33 0.5)
                                             (make-vect 0.3  0.6)
                                             (make-vect 0.1  0.4)
                                             (make-vect 0.0  0.6))) ;lower left
                              (connect (list (make-vect 0.0  0.8)
                                             (make-vect 0.1  0.6)
                                             (make-vect 0.33 0.65)
                                             (make-vect 0.4  0.65)
                                             (make-vect 0.35 0.8)
                                             (make-vect 0.4  1.0))) ;upper left
                              (connect (list (make-vect 0.75 0.0)
                                             (make-vect 0.6  0.45)
                                             (make-vect 1.0  0.15)));lower right
                              (connect (list (make-vect 1.0  0.35)
                                             (make-vect 0.8  0.65)
                                             (make-vect 0.6  0.65)
                                             (make-vect 0.65 0.8)
                                             (make-vect 0.6  1.0)))));upper right
   frame))

To modify it, we simply work at the level of the connect primitive by adding a new sequence of line segments for the smile. Here's one possible rather non-artistic definition:

(define (smile-wave frame)
  ((segments->painter (append (connect (list (make-vect 0.4  0.0)
                                             (make-vect 0.5  0.33)
                                             (make-vect 0.6  0.0))) ;inside legs
                              (connect (list (make-vect 0.25 0.0)
                                             (make-vect 0.33 0.5)
                                             (make-vect 0.3  0.6)
                                             (make-vect 0.1  0.4)
                                             (make-vect 0.0  0.6))) ;lower left
                              (connect (list (make-vect 0.0  0.8)
                                             (make-vect 0.1  0.6)
                                             (make-vect 0.33 0.65)
                                             (make-vect 0.4  0.65)
                                             (make-vect 0.35 0.8)
                                             (make-vect 0.4  1.0))) ;upper left
                              (connect (list (make-vect 0.75 0.0)
                                             (make-vect 0.6  0.45)
                                             (make-vect 1.0  0.15)));lower right
                              (connect (list (make-vect 1.0  0.35)
                                             (make-vect 0.8  0.65)
                                             (make-vect 0.6  0.65)
                                             (make-vect 0.65 0.8)
                                             (make-vect 0.6  1.0)));upper right
                              (connect (list (make-vect 0.45 0.75)
                                             (make-vect 0.5  0.7)
                                             (make-vect 0.55 0.75)));smile
                              ))
   frame))

Test:

(paint smile-wave)

Ex2.52-smilewave.png

Note that it might be useful to design a wave painter that we could arbitrarily extend by composing it with new painter procedures. If we had such a wave painter, we could add the smile by drawing the smile "on top of" the existing wave painter. This design is left as an exercise for the reader.

Solution, part B

Here's the definition of corner-split from the text. It uses procedures right-split (also defined in the text) and up-split, taken from our solution to exercise 2.44:

(define (up-split painter n)
  (if (= n 0)
      painter
      (let ((smaller (up-split painter (- n 1))))
        (below painter (beside smaller smaller)))))
 
(define (right-split painter n)
  (if (= n 0)
      painter
      (let ((smaller (right-split painter (- n 1))))
        (beside painter (below smaller smaller)))))
 
(define (corner-split painter n)
  (if (= n 0)
      painter
      (let ((up (up-split painter (- n 1)))
            (right (right-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))))))

Now let's modify corner-split per the suggestion in the problem definition by using only one copy of the up and right painters. We simply need to eliminate the use of beside and below in the definition:

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

Test:

(paint (alt-corner-split einstein 2))

Ex2.52-alt-corner-split.png

Solution, part C

Finally, part C of the problem asks us to modify the version of square-limit from the text that uses square-of-four. Here's a version that causes the "big" Einstein to look inward from each corner of the square:

(define (identity x) x)
 
(define (square-of-four tl tr bl br)
  (lambda (painter)
    (let ((top (beside (tl painter) (tr painter)))
          (bottom (beside (bl painter) (br painter))))
      (below bottom top))))
 
(define (square-limit painter n) 
  (let ((combine4 (square-of-four flip-vert rotate180
                                  identity flip-horiz)))
    (combine4 (corner-split painter n))))

Test:

(paint (square-limit einstein 2))

Ex2.52-alt-square-limit.png

Personal tools