SICPゼミ第5回

練習問題2.1

正と負の両方の引数を扱うことができる改良版make-rat を定義せよ。make-rat は符号を正規化し、正の有理数であれば分子と分母の両方が正となり、負の有理数であれば分子のみが負になるようにする。

(define (numer x) (car x))
(define (denom x) (cdr x))

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

(define (gcd a b)
  (if (= b 0)
      a(
        gcd b (remainder a b))))

(define (make-rat n d)
  (let ((g
         (cond ((and (< n 0) (< d 0)) (* -1 (gcd (* -1 n) (* -1 d))))
               ((< n 0) (gcd (* -1 n) d))
               ((< d 0) (* -1 (gcd n (* -1 d))))
               (else (gcd n d)))))
    (cons (/ n g) (/ d g))))

by pine

(define (make-rat n d)
	(let (
		(g (gcd (abs n) (abs d)))
		(sgn (/ (* n d) (abs (* n d))))
		 )
	(cons sgn (cons (/ (abs n) g) (/ (abs d) g)))
		)
	)

(define (numer x) (car (cdr x)))
(define (denom x) (cdr (cdr x)))
(define (sig x) (car x))

(define (print-rat x) 
	(cond 
		((= (sig x) 1) 
			
				(newline)
				(display (numer x))
				(display "/")
				(display (denom x))
				)
		(else 
			
				(newline)
				(display "-")
				(display (numer x))
				(display "/")
				(display (denom x))
				)
	)
	)

by どりきゃす

2.1.2 抽象化の壁

壁(barrier)とか言ってるけど階層(layer)だよね.gcdをアクセス時までに遅らせる理由がわからんけど.

練習問題2.2

平面上の線分を表現するという問題について考える。
それぞれの線分は、始点と終点という点のペアとして表す。コンストラクタmake-segment とセレクタstart-segment, end-segmentを定義せよ。さらに、点はx 座標とy 座標という数値のペアとして表現できる。最後に、定義したセレクタコンストラクタによって、線分を引数として取りその中点(両端点の座標を平均した座標を持つ点) を返すmidpoint-segment 手続きを定義せよ

(define (make-segment s e) (cons s e))
(define (start-segment x) (car x))
(define (end-segment x) (cdr x))
(define (make-point x y) (cons x y))
(define (x-point p) (car p))
(define (y-point p) (cdr p))
(define (midpoint-segment s)
  (cons (/ (+ (x-point (start-segment s)) (x-point (end-segment s))) 2)
        (/ (+ (y-point (start-segment s)) (y-point (end-segment s))) 2)))
(define (print-point p)
  (newline)
  (display "(")
  (display (x-point p))
  (display ",")
  (display (y-point p))
  (display ")"))

実行結果

gosh> (print-point (midpoint-segment (make-segment (make-point 0 2) (make-point 2 4))))

(1,3)#<undef>
練習問題2.3

長方形作れオラ

(define (make-rect x y c r) (cons c (cons r (cons x y))))
(define (get-column-length r) (car r))
(define (get-row-length r) (car(cdr r)))
(define (get-basepoint r) (cdr (cdr r)))

(define (length-of-outline r)
  (+ 
    (* 2 (get-row-length r))
    (* 2 (get-column-length r))))

(define (area r)
  (* (get-row-length r) (get-column-length r)))

点クラスの定義

(define (make-point x y) (cons x y))
(define x-point car)
(define y-point cdr)

長方形の二つの定義

(define (make-rect x y)
	(cons x y)
	)
(define left-up car)
(define right-down cdr)

対角線上の二つの頂点を保存

(define (make-rect tate yoko hidariue)
	(cons hidariue (cons tate yoko)))
(define left-up car)
(define (right-down x)
	(make-point (+ (x-point (left-up x)) (cdr (cdr x))) (- (y-point (left-up x)) (car (cdr x))) 
	))

左上の点、縦の長さ、横の長さを保存
どっちの場合でも次のように長さ、面積を求められる。

(define (len-tate x)
	(abs (- (y-point (left-up x)) (y-point (right-down x))))
	)
(define (len-yoko x)
	(abs (- (x-point (left-up x)) (x-point (right-down x)))))
(define (length x) (* 2 (+ (len-yoko x) (len-tate x))))
(define (measure x) (* (len-yoko x) (len-tate x)))

by どりきゃす

練習問題2.4

f:id:sicp-zemi:20160324154724j:plain

練習問題2.5
(define (cons_ x y)
	(* (fast-expt 2 x) (fast-expt 3 y)))

(define (how-many-divide? x n)
	(define (iter x n res)
		(cond
			((= 0 (remainder x 3)) (iter (/ x 3) n (+ res 1)))
			(else res)
			)
		)
	(iter x n 0)
	)

(define (car_ x) (how-many-divide? x 2))
(define (cdr_ x) (how-many-divide? x 3))
練習問題2.6

f:id:sicp-zemi:20160324154340j:plain

練習問題2.7

区間のコンストラクタの定義は以下のようになる。

(define (make-interval a b) (cons a b))

セレクタupper-bound とlower-bound を定義し、実装を完成させよ。

(define (make-interval a b) (cons a b))
(define upper-bound car)
(define lower-bound cdr)
練習問題2.8

引き算の手続きsub-interval を定義せよ。

(define (sub-interval a b)
  (make-interval (- (upper-bound a) (lower-bound b))
                 (- (lower-bound a) (upper-bound b))))

ついでに

(define (print-interval a)
  (display "(")
  (display (lower-bound a))
  (display "~")
  (display (upper-bound a))
  (display ")"))

実行結果

gosh> (print-interval (sub-interval (make-interval 3 2) (make-interval 4 1)))
(-2~2)#<undef>