이 문제는 복소수 표현에서 실수부, 허수부, 크기, 각을 나타내는 수를
기본수, 유리수 외 후에 만들 수를 넣을 수 있도록 만드는 문제입니다.

잘 되는군요.^^
여기서는 유리수를 선택하였습니다.
밖에 make-complex-element, selector-complex-element 프로시저를 만들어
복소수를 만들 때 make-complex-element를 부르고,
직각 좌표계에서는 실수부와 허수부, 극좌표계에서는 크기와 각에 접근할 때
selector-complex-element를 부르도록 만들었습니다.
그리고 sine, cosine을 따로 만들어 넣었습니다.
그러니 후에 다른 수를 만들어도 위에서 만든 네 개 프로시저만 신경쓰면 됩니다.
참조
해럴드 애빌슨, 김재우 역, <컴퓨터 프로그램의 구조와 해석>, 인사이트, 2007, pp. 262
(define true (= 0 0))
(define false (= 0 1))
(define (square x) (* x x))
; put/get
; in ch2support.scm - MIT support
(define (assoc key records)
(cond ((null? records) false)
((equal? key (caar records)) (car records))
(else (assoc key (cdr records)))))
(define (make-table)
(let ((local-table (list '*table*)))
(define (lookup key-1 key-2)
(let ((subtable (assoc key-1 (cdr local-table))))
(if subtable
(let ((record (assoc key-2 (cdr subtable))))
(if record
(cdr record)
false))
false)))
(define (insert! key-1 key-2 value)
(let ((subtable (assoc key-1 (cdr local-table))))
(if subtable
(let ((record (assoc key-2 (cdr subtable))))
(if record
(set-cdr! record value)
(set-cdr! subtable
(cons (cons key-2 value)
(cdr subtable)))))
(set-cdr! local-table
(cons (list key-1
(cons key-2 value))
(cdr local-table)))))
'ok)
(define (dispatch m)
(cond ((eq? m 'lookup-proc) lookup)
((eq? m 'insert-proc!) insert!)
(else (error "Unknown operation -- TABLE" m))))
dispatch))
(define operation-table (make-table))
(define get (operation-table 'lookup-proc))
(define put (operation-table 'insert-proc!))
; put-coercion / get-coercion
(define (put-coercion a b c) (put a b c))
(define (get-coercion a b) (get a b))
; section 2.5.1
(define (add x y) (apply-generic 'add x y))
(define (sub x y) (apply-generic 'sub x y))
(define (mul x y) (apply-generic 'mul x y))
(define (div x y) (apply-generic 'div x y))
; 정수
(define (install-integer-package)
(define (tag x) (attach-tag 'integer x))
(put 'add '(integer integer)
(lambda (x y) (tag (+ x y))))
(put 'sub '(integer integer)
(lambda (x y) (tag (- x y))))
(put 'mul '(integer integer)
(lambda (x y) (tag (* x y))))
(put 'div '(integer integer)
(lambda (x y) (tag (round (/ x y)))))
(put 'make 'integer
(lambda (x) (tag x)))
; exercise 2.79 answer
(put 'equ? '(integer integer)
(lambda (x y) (= x y)))
; exercise 2.80 answer
(put '=zero? '(integer)
(lambda (x) (= x 0)))
; exercise 2.81
(put 'exp '(integer integer)
(lambda (x y) (tag (expt x y))))
; exercise 2.83
(put 'raise '(integer)
(lambda (x) (make-rational x 1)))
'done)
(define (make-integer n)
((get 'make 'integer) n))
; 유리수
(define (install-rational-package)
; 프로시저
(define (numer x) (car x))
(define (denom x) (cdr x))
(define (make-rat n d)
(let ((g (gcd n d)))
(cons (/ n g) (/ d g))))
(define (add-rat x y)
(make-rat (+ (* (numer x) (denom y))
(* (numer y) (denom x)))
(* (denom x) (denom y))))
(define (sub-rat x y)
(make-rat (- (* (numer x) (denom y))
(* (numer y) (denom x)))
(* (denom x) (denom y))))
(define (mul-rat x y)
(make-rat (* (numer x) (numer y))
(* (denom x) (denom y))))
(define (div-rat x y)
(make-rat (* (numer x) (denom y))
(* (denom x) (numer y))))
; 인터페이스
(define (tag x) (attach-tag 'rational x))
(put 'add '(rational rational)
(lambda (x y) (tag (add-rat x y))))
(put 'sub '(rational rational)
(lambda (x y) (tag (sub-rat x y))))
(put 'mul '(rational rational)
(lambda (x y) (tag (mul-rat x y))))
(put 'div '(rational rational)
(lambda (x y) (tag (div-rat x y))))
(put 'make 'rational
(lambda (n d) (tag (make-rat n d))))
; exercise 2.79 answer
(put 'equ? '(rational rational)
(lambda (x y)
(and (= (numer x) (numer y)) (= (denom x) (denom y)))))
; exercise 2.83
(put 'raise '(rational)
(lambda (x)
(make-real (/ (numer x) (denom x)))))
'done)
(define (make-rational n d)
((get 'make 'rational) n d))
; 실수
(define (install-real-package)
(define (tag x) (attach-tag 'real x))
(put 'add '(real real)
(lambda (x y) (tag (+ x y))))
(put 'sub '(real real)
(lambda (x y) (tag (- x y))))
(put 'mul '(real real)
(lambda (x y) (tag (* x y))))
(put 'div '(real real)
(lambda (x y) (tag (/ x y))))
(put 'make 'real
(lambda (x) (tag x)))
; exercise 2.79 answer
(put 'equ? '(real real)
(lambda (x y) (= x y)))
; exercise 2.80 answer
(put '=zero? '(real)
(lambda (x) (= x 0)))
; exercise 2.81
(put 'exp '(real real)
(lambda (x y) (tag (expt x y))))
; exercise 2.83
(put 'raise '(real)
(lambda (x) (make-complex-from-real-imag x 0)))
'done)
(define (make-real n)
((get 'make 'real) n))
; 복소수
(define (install-complex-package)
; 프로시저
(define (make-from-real-imag x y)
((get 'make-from-real-imag 'rectangular) x y))
(define (make-from-mag-ang r a)
((get 'make-from-mag-ang 'polar) r a))
(define (add-complex z1 z2)
(make-from-real-imag (+ (real-part z1) (real-part z2))
(+ (imag-part z1) (imag-part z2))))
(define (sub-complex z1 z2)
(make-from-real-imag (- (real-part z1) (real-part z2))
(- (imag-part z1) (imag-part z2))))
(define (mul-complex z1 z2)
(make-from-mag-ang (* (magnitude z1) (magnitude z2))
(+ (angle z1) (angle z2))))
(define (div-complex z1 z2)
(make-from-mag-ang (/ (magnitude z1) (magnitude z2))
(- (angle z1) (angle z2))))
; exercise 2.81
(define (scheme-number->scheme-number n) n)
(define (complex->complex z) z)
; 인터페이스
(define (tag z) (attach-tag 'complex z))
(put 'add '(complex complex)
(lambda (z1 z2) (tag (add-complex z1 z2))))
(put 'sub '(complex complex)
(lambda (z1 z2) (tag (sub-complex z1 z2))))
(put 'mul '(complex complex)
(lambda (z1 z2) (tag (mul-complex z1 z2))))
(put 'div '(complex complex)
(lambda (z1 z2) (tag (div-complex z1 z2))))
(put 'make-from-real-imag 'complex
(lambda (x y) (tag (make-from-real-imag x y))))
(put 'make-from-mag-ang 'complex
(lambda (r a) (tag (make-from-mag-ang r a))))
; add exercise 2.77
(put 'real-part '(complex) real-part)
(put 'imag-part '(complex) imag-part)
(put 'magnitude '(complex) magnitude)
(put 'angle '(complex) angle)
; exercise 2.79 answer
(put 'equ? '(complex complex)
(lambda (x y)
(or (and (= (real-part x) (real-part y))
(= (imag-part x) (imag-part y)))
(and (= (magnitude x) (magnitude y))
(= (angle x) (angle y))))))
; exercise 2.80 answer
(put '=zero? '(complex)
(lambda (x) (or (and (= (real-part x) 0) (= (imag-part x) 0))
(and (= (magnitude x) 0) (= (angle x) 0)))))
; exercise 2.81
(put-coercion 'scheme-number 'scheme-number
scheme-number->scheme-number)
(put-coercion 'complex 'complex complex->complex)
'done)
(define (make-complex-from-real-imag x y)
((get 'make-from-real-imag 'complex) x y))
(define (make-complex-from-mag-ang r a)
((get 'make-from-mag-ang 'complex) r a))
(define (real-part z) (apply-generic 'real-part z))
(define (imag-part z) (apply-generic 'imag-part z))
(define (magnitude z) (apply-generic 'magnitude z))
(define (angle z) (apply-generic 'angle z))
; exercise 2.78
(define (attach-tag type-tag contents)
(cons type-tag contents))
(define (type-tag datum)
(cond ((pair? datum) (car datum))
(else (error "Bad tagged datum -- TYPE-TAG" datum))))
(define (contents datum)
(cond ((pair? datum) (cdr datum))
(else (error "Bad tagged datum -- CONTENTS" datum))))
; exercise 2.81
(define (exp x y) (apply-generic 'exp x y))
; exercise 2.83
(define (raise x) (apply-generic 'raise x))
; exercise 2.84
; apply-generic
(define (apply-generic op . args)
; 층수를 반환
(define (floor p)
(cond ((equal? p 'integer) 1)
((equal? p 'rational) 2)
((equal? p 'real) 3)
((equal? p 'complex) 4)
(else (error "No package " p))))
; 리스트의 최고층을 반환
(define (high-floor args-list)
(define (iter result list)
(if (null? list)
result
(if (< result (floor (type-tag (car list))))
(iter (floor (type-tag (car list))) (cdr list))
(iter result (cdr list)))))
(iter 0 args-list))
; 리스트를 살펴 최고층이 아닌 경우 raise
(define (raise-list high-floor args-list)
(if (null? args-list)
null
(if (< (floor (type-tag (car args-list))) high-floor)
(cons (raise (car args-list))
(raise-list high-floor (cdr args-list)))
(cons (car args-list)
(raise-list high-floor (cdr args-list))))))
; 리스트가 모두 같은 층인가?
(define (same-floor? args-list)
(define (iter list)
(let ((high-f (high-floor args-list)))
(cond ((null? list) true)
((< (floor (type-tag (car args-list))) high-f) false)
(else (iter (cdr list))))))
(iter args-list))
; 같은 층을 만드는 것.
(define (make-same-floor-list list)
(if (same-floor? list)
list
(make-same-floor-list (raise-list (high-floor list) list))))
; 기존의 것
(define (p-apply-generic args-list)
(let ((type-tags (map type-tag args-list)))
(let ((proc (get op type-tags)))
(if proc
(apply proc (map contents args-list))
(p-apply-generic (make-same-floor-list args-list))))))
; 실행
(p-apply-generic args))
; exercise 2.85
; project
(define (project x) (apply-generic 'project x))
; drop
(define (drop x)
(if (equ? x (raise (project x)))
(project x)
x))
; answer
(define (make-complex-element x)
(make-rational (round x) 1))
(define (selector-complex-element x)
(cons (/ (cadr (car x)) (cddr (car x)))
(/ (cadr (cadr x)) (cddr (cadr x)))))
(define (sine x) (round (sin x)))
(define (cosine x) (round (cos x)))
; section 2.4
; 직각 좌표계
(define (install-rectangular-package)
; 프로시저
(define (real-part z) (car (selector-complex-element z)))
(define (imag-part z) (cdr (selector-complex-element z)))
(define (make-from-real-imag x y) (list (make-complex-element x)
(make-complex-element y)))
(define (magnitude z)
(sqrt (+ (square (real-part z))
(square (imag-part z)))))
(define (angle z)
(atan (imag-part z) (real-part z)))
(define (make-from-mag-ang r a)
(cons (* r (cosine a)) (* r (sine a))))
; 인터페이스
(define (tag x) (attach-tag 'rectangular x))
(put 'real-part '(rectangular) real-part)
(put 'imag-part '(rectangular) imag-part)
(put 'magnitude '(rectangular) magnitude)
(put 'angle '(rectangular) angle)
(put 'make-from-real-imag 'rectangular
(lambda (x y) (tag (make-from-real-imag x y))))
(put 'make-from-mag-ang 'rectangular
(lambda (r a) (tag (make-from-mag-ang r a))))
'done)
; 극좌표계
(define (install-polar-package)
; 프로시저
(define (magnitude z) (car (selector-complex-element z)))
(define (angle z) (cdr (selector-complex-element z)))
(define (make-from-mag-ang r a) (list (make-complex-element r)
(make-complex-element a)))
(define (real-part z)
(* (magnitude z) (cosine (angle z))))
(define (imag-part z)
(* (magnitude z) (sine (angle z))))
(define (make-from-real-imag x y)
(cons (sqrt (+ (square x) (square y)))
(atan y x)))
; 인터페이스
(define (tag x) (attach-tag 'polar x))
(put 'real-part '(polar) real-part)
(put 'imag-part '(polar) imag-part)
(put 'magnitude '(polar) magnitude)
(put 'angle '(polar) angle)
(put 'make-from-real-imag 'polar
(lambda (x y) (tag (make-from-real-imag x y))))
(put 'make-from-mag-ang 'polar
(lambda (r a) (tag (make-from-mag-ang r a))))
'done)
; execute
(install-integer-package)(install-real-package)(install-rational-package)(install-complex-package)(install-rectangular-package)(install-polar-package)
(newline)
(define z1 (make-complex-from-real-imag 3 4))
(define z2 (make-complex-from-real-imag 1 2))
(define z3 (make-complex-from-mag-ang 3 4))
(define z4 (make-complex-from-mag-ang 1 2))
z1 z2 z3 z4
(newline)(newline)
(add z1 z2) (mul z1 z2)
(add z3 z4) (mul z3 z4)
- SICP Exercise 연습문제 2.89 (1)2008/03/01
- SICP Exercise 연습문제 2.88 (1)2008/03/01
- SICP Exercise 연습문제 2.87 (1)2008/03/01
- SICP Exercise 연습문제 2.86 (0)2008/02/28
- SICP Exercise 연습문제 2.85 (0)2008/02/28
- SICP Exercise 연습문제 2.84 (0)2008/02/28
- SICP Exercise 연습문제 2.83 (0)2008/02/28
글에 잘못된 점, 다른 점, 부족한 점이 있다면 지적해주세요.
댓글, 트랙백, 메일 모두 고맙습니다.







댓글을 달아 주세요