SICP/ex-3_73-82.scm

139 lines
4.4 KiB
Scheme
Raw Normal View History

2021-01-08 12:28:39 +01:00
(load "util.scm")
(define (integral integrand initial-value dt)
(define int
(cons-stream initial-value
(add-streams (scale-stream integrand dt)
int)))
int)
(display "\nex-3.73 - RC\n")
(define (RC R C dt)
(define (rc-proc i v0)
(add-streams
(scale-stream i R)
(integral (scale-stream i (/ 1 C)) v0 dt)))
rc-proc)
(define RC1 (RC 5 1 0.5))
(assert (take 5 (RC1 ones 4.2))
'(9.2 9.7 10.2 10.7 11.2))
(display "\nex-3.74 - zero-crossings\n")
(define sense-data
(list->stream
'(1 2 1.5 1 0.5 -0.1 -2 -3 -2 -0.5 0.2 3 4)))
(define response '(0 0 0 0 0 -1 0 0 0 0 1 0))
(define (sign-change-detector s2 s1)
(cond
((and (< s1 0) (>= s2 0)) 1)
((and (>= s1 0) (< s2 0)) -1)
(else 0)))
(define (make-zero-crossings input-stream last-value)
(cons-stream
(sign-change-detector (stream-car input-stream) last-value)
(make-zero-crossings (stream-cdr input-stream)
(stream-car input-stream))))
(define zero-crossings (make-zero-crossings sense-data 0))
(assert (take 12 zero-crossings) response)
(define zero-crossings
(stream-map sign-change-detector
sense-data
(cons-stream 0 sense-data)))
(assert (take 12 zero-crossings) response)
(display "\nex-3.75 - averaged zero-crossings\n")
; Louis' solution uses the average value as last-value which means that the new
; value and the previous average are used for averaging and not simply two
; consecutive values as proposed by Alyssa.
(define (make-zero-crossings-avg input-stream last-value last-avpt)
(let ((avpt (/ (+ (stream-car input-stream) last-value) 2)))
(cons-stream (sign-change-detector avpt last-avpt)
(make-zero-crossings-avg (stream-cdr input-stream)
(stream-car input-stream)
avpt))))
(display (take 12 (make-zero-crossings-avg sense-data 0 0))) (newline)
(display "\nex-3.76 - smooth zero-crossings\n")
(define (smooth xs)
(stream-map average xs (stream-cdr xs)))
(define (make-zero-crossings-smoothed input-stream last-value)
(make-zero-crossings (smooth input-stream) last-value))
(assert (take 11 (make-zero-crossings-smoothed sense-data 0))
'(0 0 0 0 0 -1 0 0 0 0 1))
2021-01-08 21:51:56 +01:00
(display "\nex-3.77 - lazy-integral\n")
(define (integral delayed-integrand initial-value dt)
(define int
(cons-stream initial-value
(let ((integrand (force delayed-integrand)))
(add-streams (scale-stream integrand dt)
int))))
int)
(define (solve f y0 dt)
(define y (integral (delay dy) y0 dt))
(define dy (stream-map f y))
y)
(assert (stream-ref (solve (lambda (y) y) 1 0.001) 1000) 2.716923932235896)
(define (integral delayed-integrand initial-value dt)
(cons-stream
initial-value
(let ((integrand (force delayed-integrand)))
(if (stream-null? integrand)
the-empty-stream
(integral (delay (stream-cdr integrand))
(+ (* dt (stream-car integrand)) initial-value)
dt)))))
(assert (stream-ref (solve (lambda (y) y) 1 0.001) 1000) 2.716923932235896)
(display "\nex-3.78 - solve-2nd\n")
; The output stream, modeling y, is generated by a network that contains a loop.
; This is because the value of d2y/dt2 depends upon the values of y and dy/dt and
; both of these are determined by integrating d2y/dt2. The diagram we would like
; to encode is shown in figure 3.35. Write a procedure solve-2nd that takes as
; arguments the constants a, b, and dt and the initial values y0 and dy0 for y
; and dy/dt and generates the stream of successive values of y.
(define (solve-2nd a b dt y0 dy0)
(define y (integral (delay dy) y0 dt))
(define dy (integral (delay ddy) dy0 dt))
(define ddy (add-streams (scale-stream dy a)
(scale-stream y b)))
y)
(assert (stream-ref (solve-2nd 1 0 0.0001 1 1) 10000)
2.7181459268252266) ; e
(assert (stream-ref (solve-2nd 0 -1 0.0001 1 0) 10472)
0.5000240628699462) ; cos pi/3 = 0.5
(assert (stream-ref (solve-2nd 0 -1 0.0001 0 1) 5236)
0.5000141490501059) ; sin pi/6 = 0.5
(display "\nex-3.79 - solve-2nd-general\n")
(define (solve-2nd-general a b) '())
2021-01-08 12:28:39 +01:00
;(display "\nex-3.80\n")
;(display "\nex-3.81\n")
;(display "\nex-3.82\n")