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))
87 (define no-sevens
88 (stream-filter (lambda (x) (not (divisible? x 7)))
89 integers))
91 (define (fibgen a b)
92 (cons-stream a (fibgen b (+ a b))))
93 (define fibs (fibgen 0 1))
95 (define (sieve s)
96 (cons-stream
97 (stream-car s)
98 (sieve (stream-filter
99 (lambda (x)
100 (not (divisible? x (stream-car s))))
101 (stream-cdr s)))))
103 ;; (define primes (sieve (integers-starting-from 2)))
104 ;; (test-case (stream-ref primes 25) 101)
106 (define ones (cons-stream 1 ones))
107 (define (add-streams s1 s2)
108 (stream-map + s1 s2))
109 (define integers (cons-stream 1 (add-streams ones integers)))
110 ;; (test-case (stream-ref integers 15) 16)
112 (define fibs
113 (cons-stream 0
114 (cons-stream 1
115 (add-streams (stream-cdr fibs)
116 fibs))))
118 (define (scale-stream stream factor)
119 (stream-map (lambda (x)
120 (* x factor))
121 stream))
122 (define double (cons-stream 1 (scale-stream double 2)))
124 (define primes
125 (cons-stream
127 (stream-filter prime? (integers-starting-from 3))))
128 (define (prime? n)
129 (define (iter ps)
130 (cond ((> (square (stream-car ps)) n) true)
131 ((divisible? n (stream-car ps)) false)
132 (else (iter (stream-cdr ps)))))
133 (iter primes))
135 (define (mul-streams s1 s2)
136 (stream-map * s1 s2))
138 (define (partial-sums s)
139 (define sums
140 (cons-stream (stream-car s)
141 (add-streams sums
142 (stream-cdr s))))
143 sums)
145 (define (merge s1 s2)
146 (cond ((stream-null? s1) s2)
147 ((stream-null? s2) s1)
148 (else
149 (let ((s1car (stream-car s1))
150 (s2car (stream-car s2)))
151 (cond ((< s1car s2car)
152 (cons-stream
153 s1car
154 (merge (stream-cdr s1) s2)))
155 ((> s1car s2car)
156 (cons-stream
157 s2car
158 (merge s1 (stream-cdr s2))))
159 (else
160 (cons-stream
161 s1car
162 (merge (stream-cdr s1) (stream-cdr s2)))))))))
164 (define (test-stream-list stream list)
165 (if (null? list)
166 'done
167 (begin (display "A: ")
168 (display (stream-car stream))
169 (display " -- ")
170 (display "E: ")
171 (display (car list))
172 (newline)
173 (test-stream-list (stream-cdr stream) (cdr list)))))
175 (define (integrate-series a)
176 (stream-map / a integers))
178 (define exp-series
179 (cons-stream 1 (integrate-series exp-series)))
181 (define cosine-series
182 (cons-stream
184 (integrate-series (stream-map - sine-series))))
185 (define sine-series
186 (cons-stream
188 (integrate-series cosine-series)))
190 (define (mul-series s1 s2)
191 (cons-stream
192 (* (stream-car s1) (stream-car s2))
193 (add-streams
194 (scale-stream (stream-cdr s2) (stream-car s1))
195 (mul-series (stream-cdr s1) s2))))
197 (define (invert-unit-series s)
198 (define x
199 (cons-stream
201 (mul-series (stream-map - (stream-cdr s))
202 x)))
203 x)
205 (define (div-series num den)
206 (let ((den-car (stream-car den)))
207 (if (zero? den-car)
208 (error "Denominator has zero constant term -- DIV-SERIES")
209 (scale-stream
210 (mul-series
211 num
212 (invert-unit-series (scale-stream den (/ 1 den-car))))
213 (/ 1 den-car)))))
216 (define (sqrt-improve guess x)
217 (define (average x y)
218 (/ (+ x y) 2))
219 (average guess (/ x guess)))
221 (define (sqrt-stream x)
222 (define guesses
223 (cons-stream
225 (stream-map (lambda (guess)
226 (sqrt-improve guess x))
227 guesses)))
228 guesses)
230 (define (pi-summands n)
231 (cons-stream (/ 1 n)
232 (stream-map - (pi-summands (+ n 2)))))
233 (define pi-stream
234 (scale-stream (partial-sums (pi-summands 1)) 4))
236 (define (euler-transform s)
237 (let ((s0 (stream-ref s 0))
238 (s1 (stream-ref s 1))
239 (s2 (stream-ref s 2)))
240 (cons-stream
241 (- s2 (/ (square (- s2 s1))
242 (+ s0 (* -2 s1) s2)))
243 (euler-transform (stream-cdr s)))))
245 (define (make-tableau transform s)
246 (cons-stream s
247 (make-tableau transform
248 (transform s))))
250 (define (stream-limit s tol)
251 (let* ((scar (stream-car s))
252 (scdr (stream-cdr s))
253 (scadr (stream-car scdr)))
254 (if (< (abs (- scar scadr)) tol)
255 scadr
256 (stream-limit scdr tol))))
258 (define (sqrt x tolerance)
259 (stream-limit (sqrt-stream x) tolerance))
261 (define (pairs s t)
262 (cons-stream
263 (list (stream-car s) (stream-car t))
264 (interleave
265 (stream-map
266 (lambda (x)
267 (list (stream-car s) x))
268 (stream-cdr t))
269 (pairs (stream-cdr s) (stream-cdr t)))))
270 (define (interleave s1 s2)
271 (if (stream-null? s1)
272 s2
273 (cons-stream (stream-car s1)
274 (interleave s2 (stream-cdr s1)))))
276 (define (display-streams n . streams)
277 (if (> n 0)
278 (begin (newline)
279 (for-each
280 (lambda (s)
281 (display (stream-car s))
282 (display " -- "))
283 streams)
284 (apply display-streams
285 (cons (- n 1) (map stream-cdr streams))))))
287 (define (all-pairs s t)
288 (cons-stream
289 (list (stream-car s) (stream-car t))
290 (interleave
291 (stream-map
292 (lambda (x)
293 (list x (stream-car t)))
294 (stream-cdr s))
295 (interleave
296 (stream-map
297 (lambda (x)
298 (list (stream-car s) x))
299 (stream-cdr t))
300 (all-pairs (stream-cdr s) (stream-cdr t))))))
302 (define (triples s t u)
303 (cons-stream
304 (list (stream-car s) (stream-car t) (stream-car u))
305 (interleave
306 (stream-cdr (stream-map (lambda (pair)
307 (cons (stream-car s) pair))
308 (pairs t u)))
309 (triples (stream-cdr s) (stream-cdr t) (stream-cdr u)))))
311 (define pythag-triples
312 (stream-filter
313 (lambda (triple)
314 (let ((i (car triple))
315 (j (cadr triple))
316 (k (caddr triple)))
317 (= (square k) (+ (square i) (square j)))))
318 (triples integers integers integers)))
320 (define (merge-weighted s1 s2 weight)
321 (cond ((stream-null? s1) s2)
322 ((stream-null? s2) s1)
323 (else
324 (let ((s1car (stream-car s1))
325 (s2car (stream-car s2)))
326 (if (<= (weight s1car) (weight s2car))
327 (cons-stream
328 s1car
329 (merge-weighted (stream-cdr s1) s2 weight))
330 (cons-stream
331 s2car
332 (merge-weighted s1 (stream-cdr s2) weight)))))))
334 (define (weighted-pairs s t weight)
335 (cons-stream
336 (list (stream-car s) (stream-car t))
337 (merge-weighted
338 (stream-map
339 (lambda (x)
340 (list (stream-car s) x))
341 (stream-cdr t))
342 (weighted-pairs (stream-cdr s) (stream-cdr t) weight)
343 weight)))
345 ;; Exercise 3.71. Numbers that can be expressed as the sum of two cubes in more than one way are sometimes called Ramanujan numbers, in honor of the mathematician Srinivasa Ramanujan.70 Ordered streams of pairs provide an elegant solution to the problem of computing these numbers. To find a number that can be written as the sum of two cubes in two different ways, we need only generate the stream of pairs of integers (i,j) weighted according to the sum i3 + j3 (see exercise 3.70), then search the stream for two consecutive pairs with the same weight. Write a procedure to generate the Ramanujan numbers. The first such number is 1,729. What are the next five?
347 (define (i3+j3 pair)
348 (let ((i (car pair))
349 (j (cadr pair)))
350 (+ (* i i i)
351 (* j j j))))
354 (define i3+j3-pairs (weighted-pairs integers integers i3+j3))
356 (define (two-same-weight s weight)
357 (let* ((scar (stream-car s))
358 (scdr (stream-cdr s))
359 (scadr (stream-car scdr)))
360 (if (= (weight scar) (weight scadr))
361 (cons-stream (list scar scadr (weight scar))
362 (two-same-weight scdr weight))
363 (two-same-weight scdr weight))))
365 ;; (define ramanujan (two-same-weight i3+j3-pairs i3+j3))
366 ;; (test-stream-list ramanujan '(1729 4104 13832 20683 32832 39312))
368 ;; Exercise 3.72. In a similar way to exercise 3.71 generate a stream of all numbers that can be written as the sum of two squares in three different ways (showing how they can be so written).
370 (define (i2+j2 pair)
371 (let ((i (car pair))
372 (j (cadr pair)))
373 (+ (* i i)
374 (* j j))))
376 (define i2+j2-pairs (weighted-pairs integers integers i2+j2))
377 (define (three-same-weight s weight)
378 (let* ((scar (stream-car s))
379 (scdr (stream-cdr s))
380 (scadr (stream-car scdr))
381 (scddr (stream-cdr scdr))
382 (scaddr (stream-car scddr)))
383 (if (= (weight scar) (weight scadr) (weight scaddr))
384 (cons-stream (list scar scadr scaddr (weight scar))
385 (three-same-weight scdr weight))
386 (three-same-weight scdr weight))))
387 (define three-ways (three-same-weight i2+j2-pairs i2+j2))
388 (display-streams 10 three-ways)