SICP 연습문제 2.52 친절한 풀이

문제

위에서 설명한 대로 층마다 따로 무언가를 고쳐서, 그림 2.9에서 나오는 wave의 square-limit를 바꾸자.

a. 연습문제 2.49에서 만든 기본 wave 페인터에 (예컨데 웃는 모습을 그린다던가 하기 위해서) 선분을 몇 개 더 그리도록 고쳐라.

b. (예컨데, up-split과 right-split 그림을 두 번 복사하지 않고 한 번만 복사해서 쓴다던가 하여) corner-split이 짜맞추는 패턴을 바꿔 보라.

c. square-of-four를 쓰는 square-limit 프로시저를 바꿔서 모서리를 다른 패턴으로 그릴 수 있게 만들어 보라. (보기를 들어, 로저스 학장 그림이 사각형의 모서리에서 바깥을 바라보도록 할 수도 있겠다.)

문제로 부터 얻은 것

다층 설계의 각 부분만을 수정하므로서 다른 계층의 프로시저들을 손보지 않고도 다양한 변형이 가능하다는 것을 느꼈습니다.

문제풀이

a. smiling wave

웃는 wave를 구현하는 것이 이 책을 공부하는 데에 얼마나 도움이 될지는 모르겠지만, 일단 만들어 보았습니다.

(define wave
(segments->painter
(list (segment (vect .25 0) (vect .35 .5))
(segment (vect .45 .85) (vect .46 .9))
(segment (vect .48 .85) (vect .46 .9))
(segment (vect .57 .85) (vect .56 .9))
(segment (vect .54 .85) (vect .56 .9))
(segment (vect .35 .5) (vect .3 .6))
(segment (vect .3 .6) (vect .15 .4))
(segment (vect .15 .4) (vect 0 .65))
(segment (vect 0 .65) (vect 0 .85))
(segment (vect 0 .85) (vect .15 .6))
(segment (vect .15 .6) (vect .3 .65))
(segment (vect .3 .65) (vect .4 .65))
(segment (vect .4 .65) (vect .35 .85))
(segment (vect .35 .85) (vect .4 1))
(segment (vect .4 1) (vect .6 1))
(segment (vect .6 1) (vect .65 .85))
(segment (vect .65 .85) (vect .6 .65))
(segment (vect .6 .65) (vect .75 .65))
(segment (vect .75 .65) (vect 1 .35))
(segment (vect 1 .35) (vect 1 .15))
(segment (vect 1 .15) (vect .6 .45))
(segment (vect .6 .45) (vect .75 0))
(segment (vect .75 0) (vect .6 0))
(segment (vect .6 0) (vect .5 .3))
(segment (vect .5 .3) (vect .4 0))
(segment (vect .4 0) (vect .25 0)))))

웃는 wave


b. corner-split

기본의 corner-split입니다.

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


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

(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))))))



위의 프로시저에서 up-split과 right-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)))))

수정된 corner-split



c. square-limit

책에서 요구한 로저스 학장 대신, 이번에도 아인슈타인이 바라보는 방향을 바꾸어 보겠습니다.

(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 identity flip-horiz
flip-vert rotate180)))
(combine4 (corner-split painter n))))

밖에서 안을 바라보고 있는 아인슈타인



읽어주셔서 감사합니다.