sicp-3-5-1-3-5-2
Posted on 2015-03-02 20:24:25 +0900 in SICP
Code from the text.
(define (stream-ref s n)
(if (= n 0)
(stream-car s)
(stream-ref (stream-cdr s) (- n 1))))
(define (stream-map proc s)
(if (stream-null? s)
the-empty-stream
(cons-stream (proc (stream-car s))
(stream-map proc (stream-cdr s)))))
(define (stream-for-each proc s)
(if (stream-null? s)
'done
(begin (proc (stream-car s))
(stream-for-each proc (stream-cdr s)))))
(define (display-stream s)
(stream-for-each display-line s))
(define (display-line x)
(newline)
(display x))
(define (stream-car stream) (car stream))
(define (stream-cdr stream) (force (cdr stream)))
(define (stream-enumerate-interval low high)
(if (> low high)
the-empty-stream
(cons-stream
low
(stream-enumerate-interval (+ low 1) high))))
(define (stream-filter pred stream)
(cond ((stream-null? stream) the-empty-stream)
((pred (stream-car stream))
(cons-stream (stream-car stream)
(stream-filter pred
(stream-cdr stream))))
(else (stream-filter pred (stream-cdr stream)))))
(stream-ref
(stream-enumerate-interval 1 100)
10)
(define (memo-proc proc)
(let ((already-run? false) (result false))
(lambda ()
(if (not already-run?)
(begin (set! result (proc))
(set! already-run? true)
result)
result))))
3.50
(define (stream-map proc . argstreams)
(if (null? (car argstreams))
the-empty-stream
(cons-stream
(apply proc (map stream-car argstreams))
(apply stream-map
(cons proc (map stream-cdr argstreams))))))
(define s1 (stream-enumerate-interval 10 100))
(define s2 (stream-enumerate-interval 20 200))
(define s3 (stream-enumerate-interval 30 300))
(define test (stream-map + s1 s2 s3))
(stream-ref test 0)
(stream-ref test 1)
(stream-ref test 2)
3.51
(define (show x)
(display-line x)
x)
(define x (stream-map show (stream-enumerate-interval 0 10)))
0
;Value: x
(stream-ref x 5)
1
2
3
4
5
;Value: 5
(stream-ref x 7)
6
7
;Value: 7
It is confusing for me to understand this memo-proc
function.
All the delayed
functions are cached after the first running.
3.52
(define sum 0)
(define (accum x)
(set! sum (+ x sum))
sum)
(define seq (stream-map accum (stream-enumerate-interval 1 20)))
; sum = 1
(define y (stream-filter even? seq))
; sum = 6
(define z (stream-filter (lambda (x) (= (remainder x 5) 0))
seq))
; sum = 10
(stream-ref y 7)
;Value: 136
(display-stream z)
; 10
; 15
; 45
; 55
; 105
; 120
; 190
; 210
; sum = 210
sum
acts as a global value, which is a bad idea in the stream.
When the delay
is memorized
, seq
is the same no matter how many times it is called.
If the non-memorized
version is used, then seq
would have different result
because of the sharing sum
.
(define sum 0)
(define (accum x)
(set! sum (+ x sum))
sum)
(define seq (stream-map accum (stream-enumerate-interval 1 20)))
;seq=(1, (accum 2), (accum 3)...(accum 20))
;sum=1
(define y (stream-filter even? seq))
;y=(6, (stream-filter even? ((accum 4), (accum 5), ...)))
;sum=6
(define z (stream-filter (lambda (x) (= (remainder x 5) 0))
seq))
;z=(15, (stream-filter (lambda (x) (...)) ((accum 5) ...)))
;sum=15
(stream-ref y 7)
;y=(6, 24, 30, 54,...)
3.53
(1 2 4 8 16 32 …)
3.54
(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-sum s)
(cons-stream
(car s)
(add-streams
(stream-cdr s)
(partial-sum s))))
3.56
(define S
(cons-stream
1 (merge (scale-stream S 2)
(merge (scale-stream S 3)
(scale-stream S 5)))))
3.57
memorized
version is $O(n)$ while naive version is $O(2^n)$
3.58
(define (expand num den radix)
(cons-stream
(quotient (* num radix) den)
(expand (remainder (* num radix) den) den radix)))
It is long divide.
3.59
(define (integrate-series s)
(stream-map / s integers))
(define sine-series
(cons-stream 0 (integrate-series cosine-series)))
(define cosine-series
(cons-stream 1
(scale-stream
(integrate-series sine-series)
-1))
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 t
(add-streams
(mul-series sine-series sine-series)
(mul-series cosine-series cosine-series)))
(display-stream t)
$(h1 + tail1) * (h2 + tail2) = h1 * h2 + h1tail2 + tail1(h2+tail2)$
3.61
(define (invert-unit-series s)
(cons-stream 1
(scale-stream
(mul-series
(stream-cdr s)
(invert-unit-series s)))))
3.62
(define (div-series num den)
(let ((den0 (stream-car den)))
(if (= den-const 0)
(error "The constant term of the denominator must be nonzero")
(scale-stream
(mul-series
num (invert-unit-series
(scale-stream den (/ 1 den-const))))
(/ 1 den-const)))))
The den
should be normalized to have the $constant=1$
Hide Comments
comments powered by Disqus