sicpm1.27〜m1.33まで(4)

simpsonのところで手間取った。(バグ取り)
sicpはムチャ振りが少ないから、やってて楽しい。
今日したこと

;;復習。
(define (sum term a next b)
  (cond ((> a b) 0)
        (else (+ (term a)
            (sum term (next a) next b)))))
(define (integral f a b dx)
  (define (add-dx x) (+ x dx))
  (* (sum f (+ a (/ dx 2.0)) add-dx b) dx))
(define (cube x) (* x x x))

;m1.29
;;if文の対応の部分がおかしくなっていた。
;;それを直すのに苦労した。
   ;;(= i n)) の)がひとつたりなかった.

(define (integral2 f a b n)
  (define (inc x) (+ x 1))
  (define h 
    (/ (- b a) n))
  (define (y k)
    (f (+ a (* k h))))
  (define (term i)
    (if (or (= i 0) (= i n))
            (y i)
            (if (odd? i)
                (* 4 (y i))
                (* 2 (y i)))))
  (* (sum term a inc  n) (/ h 3.0)))
;;全部ぴったり1/4になった。
;;	gosh> (integral2 cube 0 1 100)
;;	0.25
;;	gosh> (integral2 cube 0 1 1000)
;;	0.25
;;	gosh> (integral cube 0 1 0.01)
;;	0.24998750000000042
;;	gosh> (integral cube 0 1 0.001)
;;	0.249999875000001
;;==テスト用に使ったコード
;(define (f x)
;  (define (g i)
;    (if (or (= i 0) (= i x)) ;;こちらでは的確に動いていた。
;        (* 10 i)
;        (if (odd? i)
;            (* 100 i )
;            (* 1000 i)))))
;  (sum g 0 inc x))

;m1.30
;;sumの反復版
;;異様に簡単にできたので、確かめをする。
(define (sum2 term a next b)
  (define (iter a result)
    (if (> a b)
        result
        (iter (next a) (+ result (term a)))))
  (iter a 0))
;;実験
;;	(define (square x) (* x x))
;;	(define (f x y)
;;	  (define (inc n) (+ n 1))
;;	  (sum2 square x inc y))
;;	gosh> (f 0 10)
;;	385
;;	(確かめ) ruby -e 'p (0..10).inject(0) {|re,e|re+e**2}' #=>385
;;合ってる。

;m.1.31
(define (product term a b next)
  (define (iter result a)
    (if (> a b)
        result
        (iter (* result (term a)) (next a))))
  (iter 1 a))
(define (inc x) (+ x 1))
(define (factorial n)
  (define (f x) x)
  (product f 1 n inc))
;;	gosh> (factorial 7)
;;	5040

;4/πの計算
(define (square x) (* x x))
(define (pi/4 odd_number)
  (define (f a)
    (/ (square (inc a)) (square a)))
  (define (next n)  (+ n 2))
  (define (calc from)
    (/ (* 2.0 (product f from odd_number next)) (inc odd_number)))
  (calc 3))
;;	gosh> (pi/4 101)
;;	0.7892575441137919
;;	ruby -e 'p Math::PI/4' =>0.785398163397448

;再帰的な方のproduct
(define (product2 term a b next)
  (if (> a b)
      1
      (* (term a) (product2 term (next a) b next))))
;;上のfactorialがproduct2を使うようにし変更して実行=>成功

;m.1.32
;<1>再帰的な方
(define (accumulate combiner null-value term a next b)
  (if (> a b)
      null-value
      (combiner (term a)
                 (accumulate combiner
                             null-value
                             term
                             (next a)
                             next
                             b))))

;<2>反復的な方 
(define (accumulate2 combiner null-value term a next b)
  (define (iter a result)
    (if (> a b)
        result
        (iter (next a) (combiner result (term a))) ))
  (iter a null-value))
        ;;cube-sumの accumulate=> accumulate2で確認。成功。
  
;;試しに何かを作ってみる。
(define (cube-sum a b)
  (accumulate + 0 cube a inc b))
;;	(cube-sum 1 3) => 36

;;productだけ作ってみる
(define (product3 term a b next)
  (accumulate * 1 term a b next b))

;m1.33
(define (filltered-accumulate ok? combiner null-value term a next b)
  (define (iter a result)
    (cond ((> a b) result)
          ((ok? a) (iter (next a) (combiner result (term a))))
          (else (iter (next a) result))))
  (iter a null-value))

;;a.を解く
;prime?を使えるようにする。
(define (prime? n)
  (define (smallest-divisor n)
    (find-divisor n 2))
  (define (find-divisor n test-divisor)
    (cond ((> (square test-divisor) n) n)
          ((divides? test-divisor n) test-divisor)
          (else (find-divisor n (+ test-divisor 1)))))
  (define (divides? a b)
    (= (remainder b a) 0))
  (= n (smallest-divisor n)))
(define (square x) (* x x))

(define (a-to-b-prime-sum a b)
  (filltered-accumulate prime? + 0 square a inc b))
;;これが作ったもの
;;	gosh> (a-to-b-prime-sum 1 10)
;;	88 ;;=(+ 1 4 9 25 49)
;;bは省略。