SICP 演習問題 1.1

実はちょっと前からやっていたんだけど、長続きしないと恥ずかしいからアップするのを控えていた。

それなりに続いているし、このまま止まらないようにアップして自分を追い詰めることにした。

とりあえず1章から順番に。。。

Exercise 1.1

10
# -> 10
​
(+ 5 3 4)
# -> 12
​
(- 9 1)
#-> 8
​
(/ 6 2)
# -> 3
​
(+ (*2 4) (- 4 6))
# -> (+ 8 -2)
# -> 6
​
(define a 3)
(define b (+ a 1)
(+ a b (*a b))
# -> (+ 3 4 12)
# -> 19
​
(= a b)
# -> false
​
(if (and (> b a) (< b (*a b)))
b
a)
# -> (if (and true true)) b a)
# -> b
​
(cond ((= a 4) 6)
((= b 4) (+ 6 7 a))
(else 25))
# -> (cond (fase 6) (true 16) (else 25))
# -> 16
​
(* (cond ((> a b) a)
((< a b) b)
(else -1))
(+ a 1))
# -> (* b 4)
# -> 16

Exercise 1.2

(/ (+ 5 4 (- 2 (- 3 (+ 6 (/ 4 5)))))
(* 3 (- 6 2) (- 2 7)))

Exercise 1.3

#lang Racket
(define (sum-sqrt a b) (+ (* a a) (* b b))) 
(define (major-sum-sqrt x y z)
(cond ((and (< x y) (< x z)) (sum-sqrt y z)) 
((and (< y x) (< y z)) (sum-sqrt x z))
(else (sum-sqrt x y))))
​
(major-sum-sqrt 1 2 3)
(major-sum-sqrt 4 2 3)
(major-sum-sqrt 1 4 3)

Exercise 1.4

b>0のとき

(if (> b 0) + -)

の評価結果は + となり、 (+ a b) が評価される。 ​

他方b<0のとき

(if (> b 0) + -)

の評価結果は - となり、 (- a b) が評価される。 ​

上記の通り、 評価結果として手続き ( + or - ) が返せる =「演算子が複合式であるような組み合わせが作れる」 ということ? ​

Exercise 1.5

適用順序評価の場合、以下のように評価され、0を返す。

(test 0 (p)) ; (testを評価
(if (= x 0) 0 (p)) ; (= x 0) を評価
0

正規順序評価の場合、無限ループする

(test 0 (p)) ; (p) を評価
(test 0 (p)) ; (p) を評価
...

Exercise 1.6

new-if ではtrue 節、 else 節両方が評価されてしまうため、処理が終了しない。

(define (new-if predicate then-clause else-clause)
(cond (predicate then-clause)
(else else-clause)))
​
(define (sqrt-iter guess x)
(new-if (good-enough? guess x)
guess
(sqrt-iter (improve guess x) x)))
​
(sqrt-iter 1.0 2)
;sqrt-iterを展開
(new-if (good-enough? 1.0 2) 1.0 (sqrt-iter (improve 1.0 2) 2))
;new-if を展開
(cond (good-enough? 1.0 2) 1.0 (sqrt-iter (improve 1.0 2) 2))
;good-enough?を評価
;sqrt-iterを展開
;以下略

​ 以下の例を実行すると、
ture, else 双方が評価されていることが分かる。
(=返り値が正しくても副作用がある場合バグる

#lang Racket
(define (new-if predicate then-clause else-clause)
(cond (predicate then-clause)
(else else-clause)))
(define (then-stub) (display "I'm then-clause")(newline)(= 0 0))
(define (else-stub) (display "I'm else-clause")(newline)(= 0 1))
​
;返り値は#t(true)だが、displayはthen, else 両方出る
(new-if (> 1 0)
(then-stub)
(else-stub))
;返り値は#f(false)だが、displayはthen, else 両方出る
(new-if (> 0 1)
(then-stub)
(else-stub))

Exercise 1.7

小さい数の場合、推測値が誤差許容範囲(0.0001)よりも小さくなると、 誤差判定を必ずパスしてしまう。
(例: 10^-4のオーダーで引き算したら必ず答えは 0.0001より小さくなる) ​

大きい数の場合、小数桁がけた落ちしてしまうので、 小さい差分の比較ができなくなる。(評価が終わらない) ​ ​

Exercise 1.8

#lang Racket
(define (cube-root guess x)
(if (good-enough? guess x)
guess
(cube-root (improve guess x) x)))
(define (good-enough? guess x)
(< (abs (- (cube guess) x)) 0.001))
(define (improve guess x)
(/ (+ (/ x (square guess)) (* 2 guess)) 3))
(define (square x) (* x x))
(define (cube x) (* x x x))

(cube-root 1.0 8)