오상우
오상우

Categories

  • lisp
  • scheme
  • sicp

SW 마에스트로 멘토님의 추천으로 SICP 를 공부중이다. 책에서 사용하는 언어는 Scheme이라고 하는 Lisp의 dialect인데, 지금까지 배운 언어들과는 꽤 다르지만 재밌는 언어다.

연습문제 2.1

(define (gcd a b)
  (let ((a (abs a)) (b (abs b)))
    (if (< a b)
        (gcd b a)
        (if (= b 0)
            a
            (gcd b (remainder a b))))))

(define (make-rat x y)
  (let ((gcd-val (gcd x y)))
    (if (> 0 (* x y))
        (cons (- 0 (abs (/ x gcd-val))) (abs (/ y gcd-val)))
        (cons (abs (/ x gcd-val)) (abs (/ y gcd-val))))))
        
(define (numer x) (car x))

(define (denom x) (cdr x))

(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 (equal?-rat x y)
  (and (= (numer x) (numer y))
       (= (denom x) (denom y))))

(define (print-rat x)
  (newline)
  (display (numer x))
  (display "/")
  (display (denom x)))

; 확인
(define one-half (make-rat 1 2))
(print-rat one-half)

(define one-third (make-rat 1 -3))
(print-rat (add-rat one-half one-third))

(print-rat (mul-rat one-half one-third))

(print-rat (add-rat one-third one-third))

챕터 1이 프로시저, 로직에 관한 내용이였다면 챕터 2는 데이터에 대한 내용을 다룬다.
연습문제 2.1은 데이터 추상화를 통해 프로그램을 설계하는 방식을 유리수 데이터를 사용하여 보여주고 있다.
데이터는 기본적으로 constructor 프로시저와 selector 프로시저만 있으면 만들 수 있다는 내용이 인상적이었다.
또한 데이터를 프로시저로 요약하는 것이 서로 다른 수준의 프로시저들 사이에서 인터페이스 역할을 한다는 점도 와 닿았다.

연습문제 2.2 / 2.3

2.2 : 2차원 평면 위의 ‘점’ 데이터와 ‘선분’ 데이터를 만들고, 선분의 중점을 돌려주는 midpoint-segment 프로시저를 정의하는 문제.
2.3 : ‘직사각형’ 데이터를 만들고, 그 둘레와 넓이를 돌려주는 프로시저를 정의하는 문제.

; 2.2
(define (make-point x y) (cons x y))

(define (x-point p) (car p))

(define (y-point p) (cdr p))

(define (make-segment p1 p2) (cons p1 p2))

(define (start-segment sg) (car sg))

(define (end-segment sg) (cdr sg))

(define (avg x y) 
  (/ (+ x y) 2))

(define (midpoint-segment sg)
  (let ((start (start-segment sg)) (end (end-segment sg)))
    (make-point (avg (x-point start) (x-point end))
                (avg (y-point start) (y-point end)))))

(define (print-point p)
  (newline)
  (display "(")
  (display (x-point p))
  (display ",")
  (display (y-point p))
  (display ")"))

(define p1 (make-point 1 2))
(define p2 (make-point 6 8))
(define line1 (make-segment p1 p2))

(print-point (midpoint-segment line1))

; 2.3
(define (make-square p1 p2 p3 p4)
  (cons (cons p1 p2) (cons p3 p4)))

(define (get-p sq n)
  (cond ((= n 1) (car (car sq)))
        ((= n 2) (car (cdr sq)))
        ((= n 3) (cdr (car sq)))
        ((= n 4) (cdr (cdr sq)))))

(define (get-height sq)
  (- (y-point (get-p sq 1))
     (y-point (get-p sq 3))))

(define (get-width sq)
  (- (x-point (get-p sq 1))
     (x-point (get-p sq 2))))

(define (get-round sq)
  (+ (* 2 (get-height sq))
     (* 2 (get-width sq))))

(define (get-area sq)
  (* (get-height sq) (get-width sq)))