SICP解答メモ兼解説(1.2〜1.5)
1.1
実際に試してみてわかるのでパス
1.2
わかりやすいように分子と分母を分けて考える。まず分子から。
分子
分子は5、4、(2-(3-(6+4/5)をそれぞれ足した数。
ここで一番ネストの深い所の「6+4/5」からScheme式に表現する。Scheme式に書くと
式2を3から引く。
(+ 6 (/ 4 5)) … 式2
次に、式3を2から引く。
(- 3 (+ 6 (/ 4 5))) … 式3
そして、式4と5と4を足す。
(- 2 (- 3 (+ 6 (/ 4 5)))) … 式4
これで分子は完成。次に分母を組み立てていく。
(+ 5 4 (- 2 (- 3 (+ 6 (/ 4 5))))) … 式5
分母
分母は3、(6ー2)、(2ー7)をかけたものなので
とするだけ。
(* 3 (- 6 2) (- 2 7)) … 式6
あとは式5を式6で割る表現書けばよい。
これで完成。
(/ (+ 5 4 (- 2 (- 3 (+ 6 (/ 4 5))))) (* 3 (- 6 2) (- 2 7)))
1.3
以下のようなアルゴリズムで組み立てたい。
- x,yどちらが大きいのか?
- xの方が大きいとき
- yとzどちらが大きいのか?
- yの方が大きいとき
(* x y)
-
- zの方が大きいとき
(* x z)
- yの方が大きいとき
- xとzどちらが大きいのか?
- xの方が大きいとき
(* y x)
-
- zの方が大きいとき
これをSchemeで表現する。名前は適当につけて、
(* y z)
(define (larger-sum-of-squere x y z) (cond ((> x y) (cond ((> y z) (* x y)) ((< y z) (* x z)) )) ((< x y) (cond ((> x z) (* y x)) ((< x z) (* y z)) )) ) )
のように書く。なんかインデントが変な気がするが…あと、もっと綺麗な書き方は解答集のように特殊フォームifを使って表現すればいいと思う。あのifの使い方は「ああ、俺Lispでプログラミングしてるよ」って気分になれてよい。それにしても、アルゴリズムを文で書くと見にくいことこの上ないなあ。フローチャートでもかけばいいのだが…。
問題1.4
以下のような文追加を追加して実行してみる。
そうすると、「2」と表示される。第一引数が正なので、
(print (a-plus-abs-b 2 0))
が実行された。今度は
(+ 2 0)
としてみる。今度は「1」と表示された。これは、第一引数が負なので
(print (a-plus-abs-b -1 -2))
が実行されたことになる。このような手続きがうまくいくのは、解釈系が作用的順序で評価してるからなのだろうなあ。
(- -1 2)