Blob


1 (define (memo-proc proc)
2 (let ((already-run? false) (result false))
3 (lambda ()
4 (if already-run?
5 result
6 (begin (set! already-run? true)
7 (set! result (proc))
8 result)))))
10 (define-syntax mydelay
11 (rsc-macro-transformer
12 (let ((xfmr
13 (lambda (exp)
14 `(memo-proc (lambda () ,exp)))))
15 (lambda (e r)
16 (apply xfmr (cdr e))))))
18 (define (myforce delayed-object)
19 (delayed-object))
21 (define-syntax cons-stream
22 (rsc-macro-transformer
23 (let ((xfmr (lambda (x y) `(cons ,x (mydelay ,y)))))
24 (lambda (e r)
25 (apply xfmr (cdr e))))))
27 (define (stream-car s)
28 (car s))
29 (define (stream-cdr s)
30 (myforce (cdr s)))
31 (define stream-null? null?)
32 (define the-empty-stream '())
34 (define (integers-starting-from n)
35 (cons-stream n (integers-starting-from (+ n 1))))
37 (define (stream-ref s n)
38 (if (= n 0)
39 (stream-car s)
40 (stream-ref (stream-cdr s) (- n 1))))
41 (define (stream-map proc . argstreams)
42 (if (stream-null? (car argstreams))
43 the-empty-stream
44 (cons-stream
45 (apply proc (map stream-car argstreams))
46 (apply stream-map (cons proc (map stream-cdr argstreams))))))
47 (define (stream-for-each proc s)
48 (if (stream-null? s)
49 'done
50 (begin (proc (stream-car s))
51 (stream-for-each proc (stream-cdr s)))))
53 (define (stream-enumerate-interval low high)
54 (if (> low high)
55 the-empty-stream
56 (cons-stream
57 low
58 (stream-enumerate-interval (+ low 1) high))))
59 (define (stream-filter pred s)
60 (if (stream-null? s)
61 the-empty-stream
62 (let ((scar (stream-car s)))
63 (if (pred scar)
64 (cons-stream scar (stream-filter pred (stream-cdr s)))
65 (stream-filter pred (stream-cdr s))))))
67 (define (display-stream s)
68 (stream-for-each display-line s))
69 (define (display-line x)
70 (newline)
71 (display x))
73 (define (test-case actual expected)
74 (newline)
75 (display "Actual: ")
76 (display actual)
77 (newline)
78 (display "Expected: ")
79 (display expected)
80 (newline))
82 (define (integers-starting-from n)
83 (cons-stream n (integers-starting-from (+ n 1))))
84 (define integers (integers-starting-from 1))
86 (define (divisible? x y) (= (remainder x y) 0))
88 (define (fibgen a b)
89 (cons-stream a (fibgen b (+ a b))))
90 (define fibs (fibgen 0 1))
92 (define (sieve s)
93 (cons-stream
94 (stream-car s)
95 (sieve (stream-filter
96 (lambda (x)
97 (not (divisible? x (stream-car s))))
98 (stream-cdr s)))))
100 (define ones (cons-stream 1 ones))
101 (define (add-streams s1 s2)
102 (stream-map + s1 s2))
103 (define integers (cons-stream 1 (add-streams ones integers)))
105 (define fibs
106 (cons-stream 0
107 (cons-stream 1
108 (add-streams (stream-cdr fibs)
109 fibs))))
111 (define (scale-stream stream factor)
112 (stream-map (lambda (x)
113 (* x factor))
114 stream))
116 (define primes
117 (cons-stream
119 (stream-filter prime? (integers-starting-from 3))))
120 (define (prime? n)
121 (define (iter ps)
122 (cond ((> (square (stream-car ps)) n) true)
123 ((divisible? n (stream-car ps)) false)
124 (else (iter (stream-cdr ps)))))
125 (iter primes))
127 (define (mul-streams s1 s2)
128 (stream-map * s1 s2))
130 (define (partial-sums s)
131 (define sums
132 (cons-stream (stream-car s)
133 (add-streams sums
134 (stream-cdr s))))
135 sums)
137 (define (merge s1 s2)
138 (cond ((stream-null? s1) s2)
139 ((stream-null? s2) s1)
140 (else
141 (let ((s1car (stream-car s1))
142 (s2car (stream-car s2)))
143 (cond ((< s1car s2car)
144 (cons-stream
145 s1car
146 (merge (stream-cdr s1) s2)))
147 ((> s1car s2car)
148 (cons-stream
149 s2car
150 (merge s1 (stream-cdr s2))))
151 (else
152 (cons-stream
153 s1car
154 (merge (stream-cdr s1) (stream-cdr s2)))))))))
156 (define (test-stream-list stream list)
157 (if (null? list)
158 'done
159 (begin (display "A: ")
160 (display (stream-car stream))
161 (display " -- ")
162 (display "E: ")
163 (display (car list))
164 (newline)
165 (test-stream-list (stream-cdr stream) (cdr list)))))
167 (define (integrate-series a)
168 (stream-map / a integers))
170 (define exp-series
171 (cons-stream 1 (integrate-series exp-series)))
173 (define cosine-series
174 (cons-stream
176 (integrate-series (stream-map - sine-series))))
177 (define sine-series
178 (cons-stream
180 (integrate-series cosine-series)))
182 (define (mul-series s1 s2)
183 (cons-stream
184 (* (stream-car s1) (stream-car s2))
185 (add-streams
186 (scale-stream (stream-cdr s2) (stream-car s1))
187 (mul-series (stream-cdr s1) s2))))
189 (define (invert-unit-series s)
190 (define x
191 (cons-stream
193 (mul-series (stream-map - (stream-cdr s))
194 x)))
195 x)
197 (define (div-series num den)
198 (let ((den-car (stream-car den)))
199 (if (zero? den-car)
200 (error "Denominator has zero constant term -- DIV-SERIES")
201 (scale-stream
202 (mul-series
203 num
204 (invert-unit-series (scale-stream den (/ 1 den-car))))
205 (/ 1 den-car)))))
208 (define (sqrt-improve guess x)
209 (define (average x y)
210 (/ (+ x y) 2))
211 (average guess (/ x guess)))
213 (define (sqrt-stream x)
214 (define guesses
215 (cons-stream
217 (stream-map (lambda (guess)
218 (sqrt-improve guess x))
219 guesses)))
220 guesses)
222 (define (pi-summands n)
223 (cons-stream (/ 1 n)
224 (stream-map - (pi-summands (+ n 2)))))
225 (define pi-stream
226 (scale-stream (partial-sums (pi-summands 1)) 4))
228 (define (euler-transform s)
229 (let ((s0 (stream-ref s 0))
230 (s1 (stream-ref s 1))
231 (s2 (stream-ref s 2)))
232 (cons-stream
233 (- s2 (/ (square (- s2 s1))
234 (+ s0 (* -2 s1) s2)))
235 (euler-transform (stream-cdr s)))))
237 (define (make-tableau transform s)
238 (cons-stream s
239 (make-tableau transform
240 (transform s))))
242 (define (stream-limit s tol)
243 (let* ((scar (stream-car s))
244 (scdr (stream-cdr s))
245 (scadr (stream-car scdr)))
246 (if (< (abs (- scar scadr)) tol)
247 scadr
248 (stream-limit scdr tol))))
250 (define (sqrt x tolerance)
251 (stream-limit (sqrt-stream x) tolerance))
253 (define (pairs s t)
254 (cons-stream
255 (list (stream-car s) (stream-car t))
256 (interleave
257 (stream-map
258 (lambda (x)
259 (list (stream-car s) x))
260 (stream-cdr t))
261 (pairs (stream-cdr s) (stream-cdr t)))))
262 (define (interleave s1 s2)
263 (if (stream-null? s1)
264 s2
265 (cons-stream (stream-car s1)
266 (interleave s2 (stream-cdr s1)))))
268 (define (display-streams n . streams)
269 (if (> n 0)
270 (begin (newline)
271 (for-each
272 (lambda (s)
273 (display (stream-car s))
274 (display " -- "))
275 streams)
276 (apply display-streams
277 (cons (- n 1) (map stream-cdr streams))))))
279 (define (all-pairs s t)
280 (cons-stream
281 (list (stream-car s) (stream-car t))
282 (interleave
283 (stream-map
284 (lambda (x)
285 (list x (stream-car t)))
286 (stream-cdr s))
287 (interleave
288 (stream-map
289 (lambda (x)
290 (list (stream-car s) x))
291 (stream-cdr t))
292 (all-pairs (stream-cdr s) (stream-cdr t))))))
294 (define (triples s t u)
295 (cons-stream
296 (list (stream-car s) (stream-car t) (stream-car u))
297 (interleave
298 (stream-cdr (stream-map (lambda (pair)
299 (cons (stream-car s) pair))
300 (pairs t u)))
301 (triples (stream-cdr s) (stream-cdr t) (stream-cdr u)))))
303 (define pythag-triples
304 (stream-filter
305 (lambda (triple)
306 (let ((i (car triple))
307 (j (cadr triple))
308 (k (caddr triple)))
309 (= (square k) (+ (square i) (square j)))))
310 (triples integers integers integers)))
312 (define (merge-weighted s1 s2 weight)
313 (cond ((stream-null? s1) s2)
314 ((stream-null? s2) s1)
315 (else
316 (let ((s1car (stream-car s1))
317 (s2car (stream-car s2)))
318 (if (<= (weight s1car) (weight s2car))
319 (cons-stream
320 s1car
321 (merge-weighted (stream-cdr s1) s2 weight))
322 (cons-stream
323 s2car
324 (merge-weighted s1 (stream-cdr s2) weight)))))))
326 (define (weighted-pairs s t weight)
327 (cons-stream
328 (list (stream-car s) (stream-car t))
329 (merge-weighted
330 (stream-map
331 (lambda (x)
332 (list (stream-car s) x))
333 (stream-cdr t))
334 (weighted-pairs (stream-cdr s) (stream-cdr t) weight)
335 weight)))
337 (define (integral integrand initial-value dt)
338 (define int
339 (cons-stream initial-value
340 (add-streams (scale-stream integrand dt)
341 int)))
342 int)
344 ;; Exercise 3.74. Alyssa P. Hacker is designing a system to process signals coming from physical sensors. One important feature she wishes to produce is a signal that describes the zero crossings of the input signal. That is, the resulting signal should be + 1 whenever the input signal changes from negative to positive, - 1 whenever the input signal changes from positive to negative, and 0 otherwise. (Assume that the sign of a 0 input is positive.) For example, a typical input signal with its associated zero-crossing signal would be
346 ;;1 2 1.5 1 0.5 -0.1 -2 -3 -2 -0.5 0.2 3 4
347 ;;0 0 0 0 0 -1 0 0 0 0 1 0
349 ;; In Alyssa's system, the signal from the sensor is represented as a stream sense-data and the stream zero-crossings is the corresponding stream of zero crossings. Alyssa first writes a procedure sign-change-detector that takes two values as arguments and compares the signs of the values to produce an appropriate 0, 1, or - 1. She then constructs her zero-crossing stream as follows:
351 (define (sign-change-detector current-value last-value)
352 (cond ((and (< current-value 0) (>= last-value 0)) -1)
353 ((and (>= current-value 0) (< last-value 0)) 1)
354 (else 0)))
356 (define (make-zero-crossings input-stream last-value)
357 (cons-stream
358 (sign-change-detector (stream-car input-stream) last-value)
359 (make-zero-crossings (stream-cdr input-stream)
360 (stream-car input-stream))))
362 (define (list->stream list)
363 (if (null? list)
364 the-empty-stream
365 (cons-stream (car list)
366 (list->stream (cdr list)))))
368 ;; (define zero-crossings (make-zero-crossings sense-data 0))
370 ;; Alyssa's boss, Eva Lu Ator, walks by and suggests that this program is approximately equivalent to the following one, which uses the generalized version of stream-map from exercise 3.50:
372 (define zero-crossings
373 (stream-map sign-change-detector
374 sense-data
375 (cons-stream 0 sense-data)))
377 (define sense-data (list->stream '(1 2 1.5 1 0.5 -0.1 -2 -3 -2 -0.5 0.2 3 4)))
378 ;; (newline)
379 ;; (test-stream-list zero-crossings '(0 0 0 0 0 -1 0 0 0 0 1 0))
381 ;; Exercise 3.75. Unfortunately, Alyssa's zero-crossing detector in exercise 3.74 proves to be insufficient, because the noisy signal from the sensor leads to spurious zero crossings. Lem E. Tweakit, a hardware specialist, suggests that Alyssa smooth the signal to filter out the noise before extracting the zero crossings. Alyssa takes his advice and decides to extract the zero crossings from the signal constructed by averaging each value of the sense data with the previous value. She explains the problem to her assistant, Louis Reasoner, who attempts to implement the idea, altering Alyssa's program as follows:
383 ;; (define (make-zero-crossings input-stream last-value)
384 ;; (let ((avpt (/ (+ (stream-car input-stream) last-value) 2)))
385 ;; (cons-stream (sign-change-detector avpt last-value)
386 ;; (make-zero-crossings (stream-cdr input-stream)
387 ;; avpt))))
389 ;; The problem is that (make-zero-crossings (stream-cdr input-stream) avpt) passes avpt as the last value but this is not really the last value. This has already been averaged and so is not part of the original data.
391 (define (make-zero-crossings input-stream last-value last-avg)
392 (let ((avpt (/ (+ (stream-car input-stream) last-value) 2)))
393 (cons-stream (sign-change-detector avpt last-avg)
394 (make-zero-crossings (stream-cdr input-stream)
395 (stream-car input-stream)
396 avpt))))
398 ;; This does not correctly implement Alyssa's plan. Find the bug that Louis has installed and fix it without changing the structure of the program. (Hint: You will need to increase the number of arguments to make-zero-crossings.)
400 Exercise 3.76. Eva Lu Ator has a criticism of Louis's approach in exercise 3.75. The program he wrote is not modular, because it intermixes the operation of smoothing with the zero-crossing extraction. For example, the extractor should not have to be changed if Alyssa finds a better way to condition her input signal. Help Louis by writing a procedure smooth that takes a stream as input and produces a stream in which each element is the average of two successive input stream elements. Then use smooth as a component to implement the zero-crossing detector in a more modular style.