3.5.2 Infinite Streams

SICP再開。がんばろー。結局ひげぽんさんに追い付けなかった。
無限ストリームです。

3.53

(define s (cons-stream 1 (add-streams s s)))

はどのような結果を返すか頭で考えろ、という問題。

(stream-take s 10)
; => (1 2 4 8 16 32 64 128 256 512)

3.54 (項ごとの積を計算するmul-streamsと階乗の列factorials)

(define (mul-streams s1 s2)
  (stream-map * s1 s2))

(define factorials (cons-stream 1 (mul-streams factorials (integers-starting-from 2))))

3.55

(define (partial-sums s)
  (cons-stream (stream-car s)
               (add-streams (stream-cdr s)
                            (partial-sums s))))

(stream-take (partial-sums integers) 10)
; => (1 3 6 10 15 21 28 36 45 55)

3.56 (Hammingの問題)

2,3,5以外の数を素因数に持たない数の列を求める。

(define (merge s1 s2)
  (cond ((stream-null? s1) s2)
        ((stream-null? s2) s1)
        (else
         (let ((s1car (stream-car s1))
               (s2car (stream-car s2)))
           (cond ((< s1car s2car)
                  (cons-stream s1car (merge (stream-cdr s1) s2)))
                 ((> s1car s2car)
                  (cons-stream s2car (merge s1 (stream-cdr s2))))
                 (else
                   (cons-stream s1car
                                (merge (stream-cdr s1)
                                       (stream-cdr s2)))))))))
(define S (cons-stream 1 (merge (scale-stream S 2) 
                                (merge (scale-stream S 3)
                                       (scale-stream S 5)))))
(stream-take S 20)
; => (1 2 3 4 5 6 8 9 10 12 15 16 18 20 24 25 27 30 32 36)

3.57 (メモ化する/しない場合の計算数)

fibsの例で調べる。

(define *count* 0)
(define (%add-streams s1 s2)
  (stream-map (lambda (x y) (set! *count* (+ *count* 1)) (+ x y)) s1 s2))

(define fibs
  (cons-stream 0 (cons-stream 1 (%add-streams (stream-cdr fibs) fibs))))

(stream-take fibs 10)
; メモ化しているとき:   *count* => 9
;       していないとき: *count* => 221

3.58

以下のコードは何を表すか。

(define (expand num den radix)
  (cons-stream
    (quotient (* num radix) den)
    (expand (remainder (* num radix) den) den radix)))

分数num/denradix進数展開かな。

(stream-take (expand 2 7 7) 10)
; => (2 0 0 0 0 0 0 0 0 0)
(stream-take (expand 2 7 10) 10)
; => (2 8 5 7 1 4 2 8 5 7)

3.59 (べき級数)

べき級数の係数の無限列でいろいろする。

a (積分)
(define (integrate-series s)
  (stream-map / s integers))

これに定数項をconsしなきゃいけない。

b (ex など)
(define exp-series
  (cons-stream 1 (integrate-series exp-series)))

(define cosine-series
  (cons-stream 1 (integrate-series (stream-map - sine-series))))

(define sine-series
  (cons-stream 0 (integrate-series cosine-series)))

3.60 (級数の積)

(define (mul-series s1 s2)
  (cons-stream (* (stream-car s1) (stream-car s2))
               (add-streams (scale-stream (stream-cdr s2) (stream-car s1))
                            (mul-series (stream-cdr s1) s2))))

チェック。

(define sin^2 (mul-series   sine-series   sine-series))
(define cos^2 (mul-series cosine-series cosine-series))

(define sin^2+cos^2 (add-streams sin^2 cos^2))

(define (calc-series series x n)
  (apply + (stream-take (mul-streams series (geometric-series 1 x)) n)))

(calc-series sin^2+cos^2 10 10)
; => 0.9999999999936162
(calc-series sin^2+cos^2 100 10)
; => 0.9999930666572112
(calc-series sin^2+cos^2 0 10)
; => 1.0
(calc-series sin^2+cos^2 -1 10)
; => 1.0

3.61 (級数の逆数)

(define (invert-unit-series s)
  (cons-stream
    1
    (stream-map
      -
      (mul-series (stream-cdr s)
                  (invert-unit-series s)))))

3.62 (級数の商)

(define (div-series s1 s2)
  (let ((constant (stream-car s2)))
    (if (zero? constant)
      (error "denominator series should begin with a nonzero constant term")
      (scale-stream (mul-series s1 (invert-unit-series (scale-stream s2 (/ constant))))
                    (/ constant)))
    ))

(define tangent-series (div-series sine-series cosine-series))

でうまくいくと思ってたんだけど、ちゃんと計算できてないみたい(ここで躓いてストップしてた)。invert-unit-seriesが悪いのかとも思うけど、よくわかんないのでパス。