sicpはじめから1.13の途中まで

長い。続きを読むという表示にする方法を後で調べる。

;;練習
;;(3*((2*4) + (3+5))) + ((10-7) + 6)
(+ (* 3
      (+ (* 2 4)
	 (+ 3 5)))
   (+ (- 10 7)
      6))
;57

;;m1.1
10 ; => 10
(+ 5 3 4) ;=> 12
(-9 1) ; => 8
(/ 6 2) ; => 3
(+ (* 2 4) (- 4 6)) ;=>6

(define a 3) ;=>a
(define b (+ a 1)) ; =>b
(+ a b (* a b)) ; => 19
(= a b) ;#f ;;たぶんfalse

(if (and (> b a) (< b (* a b)))
    b
    a)
;=> 4

(cond ((= a 4) 6)
      ((= b 4) (+ 6 7 a))
      (else 25))
;=> 16

(+ 2 (if (> b a) b a))
;=>6

(* (cond ((> a b) a)
	 ((< a b) b)
	 (else -1))
   (+ a 1))
;=>16

;;m1.2
(/ (+ 5
      4
      (- 2 (- 3 (+ 6 (/ 4 5))))
      )
   (* 3 (- 6 2) (- 2 7))) 
;=>-37/150
;;後であっているか確認にしたほうがいいかも

;;m1.3
(define (g x y) (+ (* x x) (* y y)))
(define (f x y z)
  (if (<= x y) 
	 (if (<= x z) (g y z) (g y x))
	 (if (<= y z) (g x z) (g x y))))

;;m1.4
(define (a-plus-abs-b a b)
  ((if (> b 0) + -) a b))
;;こんな書き方できるんだ。なんかevalみたい
;;答えは、bの絶対値をaに足す関数。

;;m1.5
(define (p) (p))
(define (test x y)
  (if (= x 0))
  0
  y))
(test 0 (p))
;;作用的順序の場合
;;    p->p->pの無限ループ
;;正規的順序の場合
;;    if文の分岐よりx==0なので、0が出力される。

;1.1.7 平方根の計算
(define (sqrt x) 
  (define (sqrt-iter guess x)
    (if (good-enough? guess x)
	guess
	(sqrt-iter (improve guess x)
		   x)))
  (define (improve guess x)
    (average guess (/ x guess)))
  (define (average x y)
    (/ (+ x y) 2))
  (define (good-enough? guess x)
    (< (abs (- (square guess) x)) 0.001)))
;;これをさらに簡単にできるらしい。
;;||
;;\/
(define (square x) (* x x))
(define (abs x)
  (if (<= x 0) (- 0 x) x))
(define (average x y)
  (/ (+ x y) 2))
  ;上の式はわけておいた方が見やすいかも。

(define (sqrt x) 
  (define (good-enough? guess)
    (< (abs (- (square guess) x)) 0.001))
  (define (improve guess)
    (average guess (/ x guess)))
  (define (sqrt-iter guess)
    (if (good-enough? guess)
	guess
	(sqrt-iter (improve guess))))
  (sqrt-iter 1.0))
  ;たぶん、sqrtに渡されている引数は、
;その中の関数に明示的に渡さなくても使えるってことだと思う。

;;m1.6
;ifが特殊形式である理由が分からない。=特殊形式でないときに起こる問題が見付からない。
(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)))
;1.1.3の図1.1は下から順に進んでいる。
;ということで、(f (g ..) ..)のような式の場合には、最も中のものから順に計算される。
;;たぶん、これが特殊形式以外の場合の計算される順序(一般形式?)。
;;ということで、new-ifが終了していいかどうか判断しようとしたときに、
;new-ifの引数のelse-clauseの部分のsqrt-iterが計算を繰り返す。暴走->終わらない。

;m1.7
;1.7.1(小さい数、大きい数の場合good-enough?が失敗する理由を考える)
;;1,7,2
;;繰り返しから、次のguessの変化に着目
;;後で考える。

;;m1.8
(define (cubic x) (* x x x))
(define (curt x)
  (define (good-enough? guess)
    (< (abs (- (cubic guess) x)) 0.001))
  (define (improve guess)
    (/ (+ (/ x (* guess guess)) (* 2 guess)) 3))
  (define (curt-iter guess)
    (if (good-enough? guess)
    guess
    (curt-iter (improve guess))))
    (curt-iter 1.0))

;;1.2.1(再帰プロセス)
(define (factorial n)
  (if (= n 1)
      1
      (* n (factorial (- n 1)))))
;;線形再帰的プロセス(recursive process)

(define (factorial2 n)
  (define (fact-iter product counter max-count)
    (if (> counter max-count)
	product
	(fact-iter (* counter product)
		   (+ counter 1)
		   max-count)))
  (fact-iter 1 1 n))
;;反復的プロセス(iterative process)
;; 反復的プロセス分からない。たぶん、書けない。難しい。

;;これでいいような気がする…
(define (factorial3 n)
  (define (f a b)
    (if (= b 0)
	a
	(f (* a b) (- b 1))))
  (f 1 n))

;;m1.9
;;置き換えモデルめんどくさそうです><。
;;たぶん、上が再帰的。下が反復的。
;;(inc(+ (dec a) b))の方は計算が助長な感じ。
;(inc (..この中が計算終わってから))incの計算が始まると思う。

;;m1.10
;;めんどくさそう。後で考える。
;;というか、どういう風に書いたいいのか分かりません><

;1.2.2
(define (fib n)
  (cond ((= n 0) 0)
	((= n 1) 1)
	(else (+ (fib (- n 1)) (fib (- n 2))))))

(define (fib2 n)
  (define (fib-iter a b count)
    (if (= count 0)
	b
	(fib-iter (+ a b) a (- count 1))))
  (fib-iter 1 0 n))

(define (count-change amount)
  (cc amount 5))

(define (cc amount kinds-of-coins)
  (cond ((= amount 0) 1)
	((or (< amount 0) (= kinds-of-coins 0)) 0)
	(else (+ (cc amount
		     (- kinds-of-coins 1))
		 (cc (- amount
			(first-denomination kinds-of-coins))
		     kinds-of-coins)))))
(define (first-denomination kinds-of-coins)
  (cond ((= kinds-of-coins 1) 1)
	((= kinds-of-coins 2) 5)
	((= kinds-of-coins 3) 10)
	((= kinds-of-coins 4) 25)
	((= kinds-of-coins 5) 50)))

;;m1.11
(define (f1 n)
  (if (< n 3)
      n
      (+ (f1 (- n 1))
	 (* 2 (f1 (- n 2))) 
	 (* 3 (f1 (- n 3))))))
;再帰的

(define (f2 n)
  (define (f-iter a b c count)
    (if (= count n)
	a
	(f-iter (+ a (* 2 b) (* 3 c)) a b (+ count 1))))
  (if (< n 3)
      n
      (f-iter 4 2 1 3)))
;できた。反復的な方法。一応。(f1と返す値は一緒。はじめから値を入れておくってずるいような気もしないでもない。)

;;m1.12
(define (pascal n k)
  (define (calc n k)
    (cond ((= k 1) 1) 
	  ((= n k) 1)
	  (else (+ (calc (- n 1) (- k 1)) (calc (- n 1) k)))))
    (if (or (<= n 0) (<= k 0) (< n k))
	     -1
	     (calc n k)))
;;再帰的な方法

;;m1.13
;;今からやる。
;;  最も近い整数であることの証明。
;;  問いよりFib(n)=(θ-Ψ)/√5と書いてあるので、
;;  |((θ^n-(θ^n-Ψ^n))/√5| < 0.5を示せばいい。
;;  あとは、Fib(n)=(θ-Ψ)/√5が証明できればいいんだけど…分かりません><     

m1.7,m1.9(実際に紙に書く),m1.10はあとでやる。

追記

Fib(n) = (θ^n - ψ^n)/√5
証明できた。ただ計算すればいいだけだった。
その前に「ψ^2=ψ+1」を証明する必要があった。

ψ^2=1/4*(1-√5)^2
   =1/2*(3-√5)
ψ+1=1/2*(1-√5)+1
   =1/2*(3-√5)=ψ^2

これから、本題

when n=0
L:Fib(0)=0
R:θ^0+ψ^0/√5
  =0/√5
  =0
L=R

when n=1
L:Fib(1)=1
R:((1+√5)-(1-√5))/2√5
  =2√5/2√5
L=R
when n=k+1 (ただし、n=k,k-1の時に成り立つことを仮定する)
Fib(k+1)=Fiψ(k) + Fiψ(k-1)
        =(1/√5)*((θ^k-ψ^k)+(θ^(k-1)-ψ^(k-1)))/2
        =(1/2√5)*(2(1+θ)*θ^(k-1)-2((1+ψ)*ψ^(k-1)))

ここで、θ^2=θ+1, ψ^2=ψ+1より、
        =(1/2√5)*(2(θ^2)*θ^(k-1)-2(ψ^2)*ψ^(k-1))
        =(1/2√5)*(2θ^(k+1) - 2ψ^(k+1))
        =(θ^(k+1) - ψ^(k+1))/√5
        =R

証明完了。疲れた。