Sunday, February 5, 2012

SICP 2.52: Levels of Language for Robust Design

From SICP section 2.2.4 Example: A Picture Language

Just as we did in previous exercises, we can use the PLT Scheme SICP Picture Language package to run the solutions to the following exercises. You can load the picture package by putting the following (require...) expression at the beginning of your Scheme file.

(require (planet "sicp.ss" ("soegaard" "sicp.plt" 2 1)))

Exercise 2.52 asks us to make changes to the square limit of wave shown in figure 2.9 by working at the appropriate level of abstraction for the required change. (We'll need all the code we wrote in exercises 2.44 and 2.49 to start out with, so copy those into a new Scheme file.)

2.52a. Add some segments to the primitive wave painter of exercise 2.49 (to add a smile, for example).

This change requires that we make a change at a low level of abstraction, in adding segments to the wave painter itself. Let's add an eye and a smiling mouth on the left side of the head so it looks like the person in wave is looking in that direction.

; The wave painter (2.49d).
; Add some segments to form a smile (2.52a)
(define wave-segments
(list
(make-segment
(make-vect 0.006 0.840)
(make-vect 0.155 0.591))
(make-segment
(make-vect 0.006 0.635)
(make-vect 0.155 0.392))
(make-segment
(make-vect 0.304 0.646)
(make-vect 0.155 0.591))
(make-segment
(make-vect 0.298 0.591)
(make-vect 0.155 0.392))
(make-segment
(make-vect 0.304 0.646)
(make-vect 0.403 0.646))
(make-segment
(make-vect 0.298 0.591)
(make-vect 0.354 0.492))
(make-segment ; left face
(make-vect 0.403 0.646)
(make-vect 0.348 0.845))
(make-segment
(make-vect 0.354 0.492)
(make-vect 0.249 0.000))
(make-segment
(make-vect 0.403 0.000)
(make-vect 0.502 0.293))
(make-segment
(make-vect 0.502 0.293)
(make-vect 0.602 0.000))
(make-segment
(make-vect 0.348 0.845)
(make-vect 0.403 0.999))
(make-segment
(make-vect 0.602 0.999)
(make-vect 0.652 0.845))
(make-segment
(make-vect 0.652 0.845)
(make-vect 0.602 0.646))
(make-segment
(make-vect 0.602 0.646)
(make-vect 0.751 0.646))
(make-segment
(make-vect 0.751 0.646)
(make-vect 0.999 0.343))
(make-segment
(make-vect 0.751 0.000)
(make-vect 0.597 0.442))
(make-segment
(make-vect 0.597 0.442)
(make-vect 0.999 0.144))
(make-segment ; eye
(make-vect 0.395 0.916)
(make-vect 0.410 0.916))
(make-segment ; smile
(make-vect 0.376 0.746)
(make-vect 0.460 0.790))))




2.52b.
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).

For this requirement we need to work in the middle layer of abstraction. To use only one copy of the up-split and right-split images instead of two, we can simply remove the references to top-left and bottom-right that appear in the original implementation of corner-split.

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




2.52c. 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.)

We're not using the Mr. Rogers painter from the text, but we can still rearrange the square-limit painter so that the largest wave image is drawn in the four corners by simply rotating the corner-split painter by 180 degrees.

(define (square-limit painter n)
(let ((quarter (rotate180 (corner-split painter n))))
(let ((half (beside (flip-horiz quarter) quarter)))
(below (flip-vert half) half))))




Related:

For links to all of the SICP lecture notes and exercises that I've done so far, see The SICP Challenge.