sicp 2.2 계층 구조 데이터와 닫힘 성질

Post on 19-Jul-2015

140 Views

Category:

Software

2 Downloads

Preview:

Click to see full reader

TRANSCRIPT

2.2 계층 구조 데이터와닫힘 성질

Structure and Interpretation of Computer Programs

aceigy6322@gmail.com 2014.10.18

상자와 화살표 쌍을 나타내기

닫힘 성질로 계층 구조표현 가능

- 차례열(Sequence)

- 나무(Tree)

- 그림 언어(Graphic)

2.2.1 차례열(Sequence) 표현 방법

(cons ⟨a1⟩

(cons ⟨a2⟩

(cons : : :

(cons ⟨an⟩

nil): : :)))

(list ⟨a1⟩ ⟨a2⟩ : : : ⟨an⟩)

리스트 - Cons를 겹쳐 만든 쌍의 차례열

(define one-through-four (list 1 2 3 4))

• one-through-four

- (1 2 3 4)

• (car one-through-four)

- 1

• (cdr one-through-four)

- (2 3 4)

• (car (cdr one-through-four))

- 2

• (cons 10 one-through-four)

- (10 1 2 3 4)

리스트 연산

• ‘cdr연산을 가지고 흝어 내려가는’ 프로그램 기법으로 리스트 연산을 만듬.

• List-ref 프로시져 - 리스트와 수 N을 인자로 받아서, 그 리스트의 n번째 원소를 내놓음.

• List-ref 규칙

– N = 0이면, list-ref의 값은 리스트의car 이다.

– 그렇지 않으면, list-ref는 리스트의cdr에서 n-1번째 원소다.

(define (list-ref items n)

(if (= n 0)

(car items)

(list-ref (cdr items) (- n 1))))

(define squares (list 1 4 9 16 25))

(list-ref squares 3)

16

리스트 연산

• length 프로시져 - 리스트를 인자로받아 리스트의 원소가 몇 개인지 찾음.

• length 규칙– 리스트의 length는 그 리스트의 cdr

의 length에 1을 더한 값이다.

– 빈 리스트의 length는 0이다.

• Null? – 인자가 빈인자인지 판단.

(define (length items)

(if (null? items)

0

(+ 1 (length (cdr items)))))

(define odds (list 1 3 5 7))

(length odds)

4-----------------------------------------------(define (length items)

(define (length-iter a count)

(if (null? a)

count

(length-iter (cdr a) (+ 1 count))))

(length-iter items 0))

(define odds (list 1 3 5 7))

(length odds)

리스트 연산

• ‘리스트 구조를 cdr로 풀어 헤치면서, 이를 cons로 되묶어서 새로운 리스트를 만드는 방법’

• Append 프로시져 – 두 리스트를 인자로 받아 모든 원소를 한데 엮어 새 리스트를 만듬.

• Append 규칙

– List1이 빈 리스트면, 결과는 list2임.

– 그렇지 않으면, list1의 cdr와 list2를append한 다음 , 그 결과에 list1의car를 cons 한 리스트를 만듬.

(define squares (list 1 2 3 4))

(define odds (list 6 7 8 9))

(define (append list1 list2)

(if (null? list1)

list2

(cons (car list1)

(append (cdr list1) list2))))

(append squares odds)

- 1 2 3 4 6 7 8 9

리스트 매핑(Mapping)

• 리스트 연산에서 계산 방법을 요약해서 차수높은 프로시져(Higher-Order Procedure )를만든것이 Map.

• Map – 프로시져 하나와 리스트를인자로 받아, 리스트 원소마다 똑같은 프로시져를적용한 결과를 묶은리스트를 반환.

(define (scale-list items factor)(if (null? items)

null(cons (* (car items) factor)

(scale-list (cdr items)factor))))

(scale-list (list 1 2 3 4 5) 10)

(10 20 30 40 50)

---------------------------------(define items1 (list 1 2 3 4 5))(define factor1 10)

(define (scale-list1 items factor)(map (lambda (x) (* x factor))items))

(scale-list1 items1 factor1)

2.2.2 계층 구조

• 차례열을 원소로하는 차례열을나타낼수 있음.

(cons (list 1 2) (list 3 4))

• 차례열을 원소로 가지는 차례열을 나무(Tree) 꼴로 펼쳐 나타낼수있음.

Count-leaves 프로시져

• Count-leaves 프로시져 - 재귀 처리로 나무 가지를 순회하여 나뭇잎의카운터를 계산.

• Count-leaves 규칙

– 리스트 x의 length는 x의 cdr의length에 1을 더한 값이다.

– 빈 리스트의 length는 0이다.

• Pair 프로시져 – 인자로 받은 값이 쌍인지판단.

#lang scheme ;added

(define x (cons (list 1 2) (list 3 4)))

(length (list x x))

- 2

(count-leaves x)

- 4

;---------------------------------------------

(define (count-leaves x)

(cond ((null? x) 0)

((not (pair? x)) 1)

(else (+ (count-leaves (car x))

(count-leaves (cdr x))))))

나무 매핑

• Map과 재귀 처리 방식을 한데 엮어 나무꼴 데이터를 효과적으로다룰 수 있음.

• scale-tree 프로시져 – 곱할 수와나무를 인자로 받아, 모든 나뭇잎에 곱수가 곱해진 나무를 반환.

• 다른 방법은 나무를 부분 나무의차례열로 보고, map을 사용.

(define (scale-tree tree factor)(cond ((null? tree) null)

((not (pair? tree)) (* tree factor))(else (cons (scale-tree (car tree) factor)

(scale-tree (cdr tree) factor)))))(scale-tree (list 1 (list 2 (list 3 4) 5) (list 6 7)) 10)

-------------------------------------------------------

(define tempTree (list 1 (list 2 (list 3 4) 5) (list 6 7)))

(define (scale-tree tree factor)(map (lambda (sub-tree1)

(if (pair? sub-tree1)(scale-tree sub-tree1 factor)(* sub-tree1 factor)))

tree))

(scale-tree tempTree 10);(10 (20 (30 40) 50) (60 70))

2.2.3 공통 인터페이스로써 차례열의 쓰임새

• 나무꼴 데이터를 인자로

받아서 잎사귀 가운데 홀수인

것만 제곱한 다음에 이것을 모두

더한 값을 반환

------------------------------------

• N보다 작거나 N과 같은

정수 K에 대하여 피보나치 수열

Fib(k) 값을 구한 후 짝수만

모아서 리스트로 묶어내는

프로시져

(define (square x) (* x x))(define (sum-odd-squares tree)(cond ((null? tree) 0)

((not (pair? tree))(if (odd? tree) (square tree) 0))(else (+ (sum-odd-squares (car tree))

(sum-odd-squares (cdr tree))))))

----------------------------------------------------

(define (even-fibs n)(define (next k)(if (> k n)

null(let ((f (fib (k))))(if (even? f)

(cons f (next (+ k 1)))(next (+ k 1))))))

(next 0))

• 처리 과정이 비슷함.

• 그러나 두 프로시져는 신호가 흘러가는 구조를 갖추지 못하였음.

• 따라서 두 프로시저 정의에서는 신호 흐름 방식의 단계별 처리 과정이 확실히 대응하는 부분을 찾기 힘듬.

차례열 연산

• 계산 단계에서 다음 계산 단계로 흘러가는신호를 리스트로 나타내면, 모든 단계별처리 과정을 리스트 연산이 가능함.

• 모듈 방식으로 독립된 부품을 짜 맞추듯이프로그램을 설계

Map

• (map square (list 1 2 3 4 5))

• (1 4 9 16 25)

Filter

(define (filter predicate sequence)(cond ((null? sequence) nil)

((predicate (car sequence))(cons (car sequence)

(filter predicate (cdr sequence))))(else (filter predicate (cdr sequence)))))

(filter odd? (list 1 2 3 4 5))

(1 3 5)

Accumulate

(define (accumulate op initial sequence)(if (null? sequence)

initial(op (car sequence)

(accumulate op initial (cdr sequence)))))

(accumulate + 0 (list 1 2 3 4 5))15

(accumulate * 1 (list 1 2 3 4 5))120

Enumerate

(define (enumerate-tree tree)

(cond ((null? tree) nil)

((not (pair? tree)) (list tree))

(else (append (enumerate-tree (car tree))

(enumerate-tree (cdr tree))))))

(enumerate-tree (list 1 (list 2 (list 3 4)) 5))

(1 2 3 4 5)

(define (enumerate-interval low high)

(if (> low high)

nil

(cons low (enumerate-interval (+ low 1) high))))

(enumerate-interval 2 7)

(2 3 4 5 6 7)

모듈 조합

(define (sum-odd-squares tree)

(accumulate +

0

(map square

(filter odd?

(enumerate-tree tree)))))

----------------------------------------------------------------------------

(define (even-fibs n)

(accumulate cons

nil

(filter even?

(map fib

(enumerate-interval 0 n)))))

겹친 매핑

• 차례열 패러다임의 쓰임새를 넓혀서, 겹친 루프를 써서 나타낼 수있는 계산 문제를 표현

• 양의 정수 n, I, j가 있을때, 1 <= j < I <= n 만족하고 I + j 의 값이소수가 되는 i와 j의 모든 순서 쌍을 구하는 문제

• N = 6 일 경우.

• Enumerate– n보다 작거나 같은 양의

정수로 이루어진 모든 순서쌍을 차례열로 묶어냄

• Filter– 그 가운데 그 합이 소수인

쌍들만 거르개로 고름.

• Map– 골라낸 쌍(I,j)에 대해 트리

플(I,j, i+j)를 만듬.

• Accumulate

(accumulate append

nil

(map (lambda (i)

(map (lambda ( j) (list i j))

(enumerate-interval 1 (- i 1))))

(enumerate-interval 1 n)))

(define (flatmap proc seq)

(accumulate append nil (map proc seq)))

----------------------------------------------------------

(define (prime-sum? pair)

(prime? (+ (car pair) (cadr pair))))

----------------------------------------------------------

(define (make-pair-sum pair)

(list (car pair) (cadr pair)

(+ (car pair) (cadr pair))))

(define (prime-sum-pairs n)

(map make-pair-sum

(filter prime-sum?

(flatmap

(lambda (i)

(map (lambda ( j) (list i j))

(enumerate-interval 1 (- i 1))))

(enumerate-interval 1 n)))))

(define (enumerate-interval low high)(if (> low high)

null(cons low (enumerate-interval (+ low 1) high))));------------------------------------------------

(define (accumulate append null)((map (lambda (i)

(map (lambda (j) (list i j))(enumerate-interval 1 (- i 1))))

(enumerate-interval 1 n))))

(define (flatmap proc seq)(accumulate append null (map proc seq)))

;----------------------------------------------------------(define (square x) (* x x))

(define (find-divisor n test-divisor)(cond ((> (square test-divisor) n) n)

((divides? test-divisor n) test-divisor)(else (find-divisor n (+ test-divisor 1)))))

(define (divides? a b) (= (remainder b a) 0))

(define (smallest-divisor n) (find-divisor n 2))

(define (prime? n)(= n (smallest-divisor n)))

(define (prime-sum? pair)(prime? (+ (car pair) (cadr pair))))

;----------------------------------------------------------(define (make-pair-sum pair)

(list (car pair) (cadr pair) (+ (car pair) (cadr pair))))

;----------------------------------------------------------

(define (prime-sum-pairs n)(map make-pair-sum

(filter prime-sum? (flatmap (lambda (i)

(map (lambda (j) (list i j))

(enumerate-interval 1 (- i 1))))(enumerate-interval 1 n)))))

2.2.4 그림 언어

• 데이터 요약과 닫힘 성질, 아울러 차수 높은

프로시저가 프로그램 설계에 미치는 힘을

살펴보기 위해 그림을 그리는데 쓰는 간단한

그림 언어를 만들어 보자.

• 그림언어는 페인터라는 한가지 요소만 갖춤.

• Wave 라는 기본 페인터를 써서 그린 그림.

• Rogers 페인터 사용.

(define wave2 (beside wave (flip-vert wave)))

(define wave4 (below wave2 wave2))

(define (flipped-pairs painter)(let ((painter2 (beside painter (flip-vert painter))))(below painter2 painter2)))

(define wave4 (flipped-pairs wave))

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

그림틀

Origin(Frame) + x Edge1(Frame) + y Edge2(Frame)

(define (frame-coord-map frame)

(lambda (v)

(add-vect

(origin-frame frame)

(add-vect (scale-vect (xcor-vect v) (edge1-frame frame))

(scale-vect (ycor-vect v) (edge2-frame

frame))))))

((frame-coord-map a-frame) (make-vect 0 0))

(origin-frame a-frame)

페인터

• 페인터 프로시져는 그림틀을 인자로 받아서, 그 틀에 맞춘 그림을 그림.

(define (segments->painter segment-list)

(lambda (frame)

(for-each

(lambda (segment)

(draw-line

((frame-coord-map frame) (start-segment segment))

((frame-coord-map frame) (end-segment segment))))

segment-list)))

단단하게 설계할 때 쓰는 언어

• 다층 설계 – 단계별로 여러 언어를 쌓아올려 복잡한 시스템을 층층이 짜맞추어 가는방법

• 다층 설계 방식은 프로그램을 “튼튼하게” 짜는데 큰 도움을 줌.

Referance

• 컴퓨터 프로그램의 구조와 해석 2/E – 헤럴드에빌슨, 제럴드 제이 서스먼, 줄리 서스먼 지음. 인사이트.

top related