SICP 問題 2.2(線分を作る)
休み時間中に問題文だけでも。。
問題
平面上の線分を表現する問題を考えよう。各線分は一対の点:始発点と終着点で表現されている
点を使って線分を表現する構成子 make-segment と選択子 start-segment と end-segment を定義せよ。
更に点は一対の数:x 座標と y 座標で表現することができる。
従ってこの表現を定義する構成子 make-point と選択子 x-point と y-point を規定せよ。
最後に選択子と構成子を使い、引数として線分をとり、中間点(座標が両端点の座標の平均である点)を返す手続き
midpoint-segment を定義せよ。その手続きを使ってみるには、点を印字する方法が必要である。
(define (print-point p) (newline) (display "(") (display (x-point p)) (display ",") (display (y-point p)) (display ")"))
解答
make-segment は、線分を作るために引数として2つの座標をとる手続きになる。
また、始点座標、終点座標を取得する手続きは1つの線分を引数にとる。
この考え方はそんなに難しかないだろう。
;線分生成手続き (define (make-segment p0 p1) (cons p0 p1)) ;始点座標を取得する手続き (define (start-segment s) (car s)) ;終点座標を取得する手続き (define (end-segment s) (cdr s))
次は make-segment の引数となる座標が主役。
座標を生成する手続き make-point は、引数に x 座標、y 座標をとる。
x 座標、y 座標を取得する手続きは、それぞれ引数に座標をとる。
;座標生成手続き (define (make-point x y) (cons x y)) ;x 座標取得手続き (define (x-point p) (car p)) ;y 座標取得手続き (define (y-point p) (cdr p))
最後、線分を引数にとってその中間点を返す手続き。
素直に書くとこんな感じ?
(define (midpoint-segment s) ;平均を取得する (define (average a b) (/ (+ a b) 2)) ;座標をすべて取得 (let* ((p0 (start-segment s)) (p1 (end-segment s))) (make-point (average (x-point p0) (x-point p1)) (average (y-point p0) (y-point p1)))))
問題文には求めた中間点を表示する為の手続きが必要とあるが、ここで使っているデータは、単なるリストなので、gaucheを使うとそのまま表示できるので略。
さて、これらを使って線分の中間点を求めてみる。
い〜んじゃな〜い?
gosh> (midpoint-segment (make-segment (make-point 0 0) (make-point 5 10)))
(5/2 . 5)
gosh> (midpoint-segment (make-segment (make-point -2 -3) (make-point 5 10)))
(3/2 . 7/2)
gosh> (midpoint-segment (make-segment (make-point -2 1) (make-point 5 10)))
(3/2 . 11/2)
gosh> (midpoint-segment (make-segment (make-point 5 10) (make-point -2 1)))
(3/2 . 11/2)
gosh>