diff options
author | Jacques Comeaux <jacquesrcomeaux@protonmail.com> | 2023-10-20 17:40:49 -0500 |
---|---|---|
committer | Jacques Comeaux <jacquesrcomeaux@protonmail.com> | 2023-10-20 17:40:49 -0500 |
commit | f9710fddeb1d7b76e22dae958285bc7562ac198a (patch) | |
tree | 95ce0f25054ba12d03e1968299a65ec28e3ad875 | |
parent | 58dcd1897b1a5b922afbc423aca9f06e8b915578 (diff) |
Finish chapter 3 part 5
-rw-r--r-- | chap3/part5.rkt | 929 |
1 files changed, 929 insertions, 0 deletions
diff --git a/chap3/part5.rkt b/chap3/part5.rkt new file mode 100644 index 0000000..a12a778 --- /dev/null +++ b/chap3/part5.rkt @@ -0,0 +1,929 @@ +#lang sicp +(#%require (only racket/base print-as-expression print-mpair-curly-braces)) +(print-as-expression #f) +(print-mpair-curly-braces #f) + +;; Chapter 3 +;; Modularity, Objects, and State + +;; 3.5 +;; Streams + +;; Streams Are Delayed Lists + +(#%provide stream-car) +(define (stream-car stream) (car stream)) + +(#%provide stream-cdr) +(define (stream-cdr stream) (force (cdr stream))) + +(#%provide stream-ref) +(define (stream-ref s n) + (if (= n 0) + (stream-car s) + (stream-ref (stream-cdr s) (- n 1)))) + +(#%provide stream-map) +(define (stream-map proc s) + (if (stream-null? s) + the-empty-stream + (cons-stream + (proc (stream-car s)) + (stream-map proc (stream-cdr s))))) + +(#%provide stream-for-each) +(define (stream-for-each proc s) + (if (stream-null? s) + 'done + (begin + (proc (stream-car s)) + (stream-for-each proc (stream-cdr s))))) + +(#%provide display-stream) +(define (display-stream s) + (stream-for-each display-line s)) + +(#%provide display-line) +(define (display-line x) + (newline) + (display x)) + +(#%provide stream-enumerate-interval) +(define (stream-enumerate-interval low high) + (if (> low high) + the-empty-stream + (cons-stream + low + (stream-enumerate-interval + (+ low 1) + high)))) + +(#%provide stream-filter) +(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))))) + +(#%provide prime?) +(define (prime? n) + (define (square x) (* x x)) + (define (divides? a b) (= (remainder b a) 0)) + (define (smallest-divisor) (find-divisor 2)) + (define (find-divisor test-divisor) + (define (next i) (if (= i 2) 3 (+ i 2))) + (cond + ((> (square test-divisor) n) n) + ((divides? test-divisor n) test-divisor) + (else (find-divisor (next test-divisor))))) + (= n (smallest-divisor))) + +#| (define (force delayed-object) |# +#| (delayed-object)) |# + +(#%provide memo-proc) +(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)))) + +#| (delay ...) = (memo-proc (lambda () ...)) |# + +#| 3.50 |# + +(#%provide stream-map-) +(define (stream-map- proc . argstreams) + (if (stream-null? (car argstreams)) + the-empty-stream + (cons-stream + (apply proc (map stream-car argstreams)) + (apply + stream-map- + (cons proc (map stream-cdr argstreams)))))) + +#| 3.51 |# + +(#%provide show) +(define (show x) (display-line x) x) + +#| (define x (stream-map show (stream-enumerate-interval 0 10))) |# + +#| 0 |# + +#| (stream-ref x 5) |# + +#| 1 |# +#| 2 |# +#| 3 |# +#| 4 |# +#| 55 |# + +#| (stream-ref x 7) |# + +#| 6 |# +#| 77 |# + +#| 3.52 |# + +#| (define sum 0) ;; sum = 0 |# +#| (define (accum x) (set! sum (+ x sum)) sum) ;; sum = 0 |# +#| (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) ;; sum = 136 |# +#| (display-stream z) ;; sum = 210 |# + +;; Infinite Streams + +(#%provide integers-starting-from) +(define (integers-starting-from n) + (cons-stream n (integers-starting-from (+ n 1)))) + +(#%provide integers) +(define integers (integers-starting-from 1)) + +(define (divisible? x y) (= (remainder x y) 0)) + +(#%provide no-sevens) +(define no-sevens + (stream-filter + (lambda (x) + (not (divisible? x 7))) + integers)) + +(define (fibgen a b) + (cons-stream a (fibgen b (+ a b)))) + +(#%provide fibs) +(define fibs (fibgen 0 1)) + +(#%provide sieve) +(define (sieve stream) + (cons-stream + (stream-car stream) + (sieve + (stream-filter + (lambda (x) (not (divisible? x (stream-car stream)))) + (stream-cdr stream))))) + +(#%provide primes) +(define primes (sieve (integers-starting-from 2))) + +(#%provide ones) +(define ones (cons-stream 1 ones)) + +(#%provide add-streams) +(define (add-streams s1 s2) + (stream-map- + s1 s2)) + +(#%provide integers-) +(define integers- (cons-stream 1 (add-streams ones integers-))) + +(#%provide fibs-) +(define fibs- + (cons-stream + 0 + (cons-stream + 1 + (add-streams + (stream-cdr fibs-) + fibs-)))) + +(#%provide scale-stream) +(define (scale-stream stream factor) + (stream-map + (lambda (x) (* x factor)) + stream)) + +(#%provide double) +(define double (cons-stream 1 (scale-stream double 2))) + +(define (square x) (* x x)) + +(#%provide primes-) +(define primes- + (cons-stream + 2 + (stream-filter prime? (integers-starting-from 3)))) + +(define (prime?- n) + (define (iter ps) + (cond + ((> (square (stream-car ps)) n) true) + ((divisible? n (stream-car ps)) false) + (else (iter (stream-cdr ps))))) + (iter primes-)) + +#| 3.53 |# + +#| (define s (cons-stream 1 (add-streams s s))) |# +#| 1, 2, 4, 8, 16, ... |# + +#| 3.54 |# + +(#%provide mul-streams) +(define (mul-streams s1 s2) + (stream-map- * s1 s2)) + +(#%provide factorials) +(define factorials (cons-stream 1 (mul-streams (stream-cdr integers) factorials))) + +#| 3.55 |# + +(#%provide partial-sums) +(define (partial-sums stream) + (cons-stream + (stream-car stream) + (stream-map- + (lambda (x) (+ x (stream-car stream))) + (partial-sums (stream-cdr stream))))) + +#| 3.56 |# + +(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))))))))) + +(#%provide S) +(define S + (cons-stream + 1 + (merge + (scale-stream S 2) + (merge + (scale-stream S 3) + (scale-stream S 5))))) + +#| 3.58 |# + +(#%provide expand) +(define (expand num den radix) + (cons-stream + (quotient (* num radix) den) + (expand (remainder (* num radix) den) den radix))) + +;; expansion of a rational number in the given base + +#| 3.59 |# + +(#%provide integrate-series) +(define (integrate-series stream) + (stream-map- / stream integers)) + +(#%provide exp-series) +(define exp-series + (cons-stream 1 (integrate-series exp-series))) + +(#%provide cosine-series) +(define cosine-series + (cons-stream 1 (scale-stream (integrate-series sine-series) -1))) + +(#%provide sine-series) +(define sine-series + (cons-stream 0 (integrate-series cosine-series))) + +#| 3.60 |# + +(#%provide mul-series) +(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)))) + +#| 3.61 |# + +(#%provide invert-unit-series) +(define (invert-unit-series series) + (define result + (cons-stream + 1 + (scale-stream + (mul-series (stream-cdr series) result) + -1))) + result) + +#| 3.62 |# + +(#%provide div-series) +(define (div-series s1 s2) + (cond + ((= 0 (stream-car s2)) + (error "Zero constant term in denominator -- DIV_SERIES")) + (else + (let ((factor (/ 1 (stream-car s2)))) + (mul-series + (scale-stream s1 factor) + (invert-unit-series (scale-stream s2 factor))))))) + +(#%provide tangent-series) +(define tangent-series + (div-series sine-series cosine-series)) + +;; Exploiting the Stream Paradigm + +(define (average x y) + (/ (+ x y) 2)) + +(define (sqrt-improve guess x) + (average guess (/ x guess))) + +(#%provide sqrt-stream) +(define (sqrt-stream x) + (define guesses + (cons-stream + 1.0 + (stream-map + (lambda (guess) + (sqrt-improve guess x)) + guesses))) + guesses) + +(define (pi-summands n) + (cons-stream + (/ 1.0 n) + (stream-map - (pi-summands (+ n 2))))) + +(#%provide pi-stream) +(define pi-stream + (scale-stream + (partial-sums (pi-summands 1)) + 4)) + +(#%provide euler-transform) +(define (euler-transform s) + (let + ((s0 (stream-ref s 0)) + (s1 (stream-ref s 1)) + (s2 (stream-ref s 2))) + (cons-stream + (- + s2 + (/ + (square (- s2 s1)) + (+ s0 (* -2 s1) s2))) + (euler-transform (stream-cdr s))))) + +(define (make-tableau transform s) + (cons-stream + s + (make-tableau transform (transform s)))) + +(#%provide accelerated-sequence) +(define (accelerated-sequence transform s) + (stream-map stream-car (make-tableau transform s))) + +#| 3.63 |# + +(#%provide sqrt-stream-bad) +(define (sqrt-stream-bad x) + (cons-stream + 1.0 + (stream-map + (lambda (guess) + (sqrt-improve guess x)) + (sqrt-stream-bad x)))) + +;; no memoization + + +#| 3.64 |# + +(#%provide stream-limit) +(define (stream-limit stream tolerance) + (let + ((s0 (stream-ref stream 0)) + (s1 (stream-ref stream 1))) + (if (< (abs (- s0 s1)) tolerance) + s1 + (stream-limit (stream-cdr stream) tolerance)))) + +(#%provide sqrt-) +(define (sqrt- x tolerance) + (stream-limit (sqrt-stream x) tolerance)) + +#| 3.65 |# + +(define (ln2-summands n) + (cons-stream + (/ 1.0 n) + (stream-map - (ln2-summands (+ n 1))))) + +(#%provide ln2-stream) +(define ln2-stream + (partial-sums (ln2-summands 1))) + +(#%provide ln2-faster) +(define ln2-faster + (euler-transform ln2-stream)) + +(#%provide ln2-fastest) +(define ln2-fastest + (accelerated-sequence euler-transform ln2-stream)) + +#| (stream-filter |# +#| (lambda (pair) |# +#| (prime? (+ (car pair) (cadr pair)))) |# +#| int-pairs) |# + +(#%provide interleave) +(define (interleave s1 s2) + (if (stream-null? s1) + s2 + (cons-stream + (stream-car s1) + (interleave s2 (stream-cdr s1))))) + +(#%provide pairs) +(define (pairs s t) + (cons-stream + (list (stream-car s) (stream-car t)) + (interleave + (stream-map + (lambda (x) (list (stream-car s) x)) + (stream-cdr t)) + (pairs (stream-cdr s) (stream-cdr t))))) + +(#%provide stream-append) +(define (stream-append s1 s2) + (if (stream-null? s1) + s2 + (cons-stream + (stream-car s1) + (stream-append (stream-cdr s1) s2)))) + +#| 3.66 |# + +#| (pairs integers integers) |# +;; second number in pair gets large more quickly + +#| 3.67 |# + +(#%provide pairs-all) +(define (pairs-all s t) + (cons-stream + (list (stream-car s) (stream-car t)) + (interleave + (interleave + (stream-map + (lambda (x) (list (stream-car s) x)) + (stream-cdr t)) + (stream-map + (lambda (x) (list x (stream-car t))) + (stream-cdr s))) + (pairs-all (stream-cdr s) (stream-cdr t))))) + +#| 3.68 |# + +(#%provide pairs-bad) +(define (pairs-bad s t) + (interleave + (stream-map + (lambda (x) + (list (stream-car s) x)) + t) + (pairs-bad (stream-cdr s) (stream-cdr t)))) + +;; interleave needs the car of its second argument. but +;; since pairs-bad does not use a cons, this will loop +;; infinitely without producing any values + +#| 3.69 |# + +(#%provide triples) +(define (triples s t u) + (cons-stream + (list (stream-car s) (stream-car t) (stream-car u)) + (interleave + (stream-map + (lambda (xy) (cons (stream-car s) xy)) + (interleave + (stream-map + (lambda (x) (list (stream-car t) x)) + (stream-cdr u)) + (pairs (stream-cdr t) (stream-cdr u)))) + (triples (stream-cdr s) (stream-cdr t) (stream-cdr u))))) + +(#%provide pythagorean-triples) +(define pythagorean-triples + (stream-filter + (lambda (ijk) + (let + ((i (car ijk)) + (j (cadr ijk)) + (k (caddr ijk))) + (= + (+ (square i) (square j)) + (square k)))) + (triples integers integers integers))) + +#| 3.70 |# + +(#%provide merge-weighted) +(define (merge-weighted s1 s2 weight) + (cond + ((stream-null? s1) s2) + ((stream-null? s2) s1) + (else + (let + ((s1car (stream-car s1)) + (s2car (stream-car s2))) + (let + ((s1weight (weight s1car)) + (s2weight (weight s2car))) + (cond + ((< s1weight s2weight) + (cons-stream + s1car + (merge-weighted (stream-cdr s1) s2 weight))) + ((> s1weight s2weight) + (cons-stream + s2car + (merge-weighted s1 (stream-cdr s2) weight))) + (else + (cons-stream + s1car + (cons-stream + s2car + (merge-weighted (stream-cdr s1) (stream-cdr s2) weight)))))))))) + + +(#%provide weighted-pairs) +(define (weighted-pairs s t weight) + (cons-stream + (list (stream-car s) (stream-car t)) + (merge-weighted + (stream-map (lambda (x) (list (stream-car s) x)) (stream-cdr t)) + (weighted-pairs (stream-cdr s) (stream-cdr t) weight) + weight))) + +(#%provide ijs-sum) +(define ijs-sum + (weighted-pairs + integers + integers + (lambda (xy) (apply + xy)))) + +(#%provide ijs-235) +(define ijs-235 + (let + ((not235 + (stream-filter + (lambda (x) (not (divisible? x 5))) + (stream-filter + (lambda (x) (not (divisible? x 3))) + (stream-filter + (lambda (x) (not (divisible? x 2))) + integers))))) + (weighted-pairs + not235 + not235 + (lambda (xy) + (let + ((i (car xy)) + (j (cadr xy))) + (+ (* 2 i) (* 3 j) (* 5 i j))))))) + +#| 3.71 |# + +(define (cube x) (* x x x)) + +(define sum-of-cubes + (lambda (xy) + (+ (cube (car xy)) (cube (cadr xy))))) + +(define (same-2-weights stream weight) + (let + ((s0 (stream-ref stream 0)) + (s1 (stream-ref stream 1))) + (if (= (weight s0) (weight s1)) + (cons-stream + (weight s0) + (same-2-weights (stream-cdr stream) weight)) + (same-2-weights (stream-cdr stream) weight)))) + +(#%provide ramanujan-numbers) +(define ramanujan-numbers + (same-2-weights + (weighted-pairs + integers + integers + sum-of-cubes) + sum-of-cubes)) + +#| 1729 |# +#| 4104 |# +#| 13832 |# +#| 20683 |# +#| 32832 |# +#| 39312 |# + +#| 3.72 |# + +(define (same-3-weights stream weight) + (let + ((s0 (stream-ref stream 0)) + (s1 (stream-ref stream 1)) + (s2 (stream-ref stream 2))) + (if + (and + (= (weight s0) (weight s1)) + (= (weight s0) (weight s2))) + (cons-stream + (list s0 s1 s2) + (same-3-weights (stream-cdr stream) weight)) + (same-3-weights (stream-cdr stream) weight)))) + +(define (display-sum-of-cubes xy) + (let + ((x (car xy)) + (y (cadr xy))) + (display x) + (display "^3 + ") + (display y) + (display "^3 = ") + (display (sum-of-cubes xy)) + (newline))) + +(#%provide taxicab-3) +(define (taxicab-3) + (stream-for-each + (lambda (xyz) + (for-each display-sum-of-cubes xyz)) + (same-3-weights + (weighted-pairs + integers + integers + sum-of-cubes) + sum-of-cubes))) + +(#%provide integral) +(define (integral integrand initial-value dt) + (define int + (cons-stream + initial-value + (add-streams + (scale-stream integrand dt) + int))) + int) + +#| 3.73 |# + +(#%provide RC) +(define (RC R C dt) + (lambda (i v0) + (add-streams + (scale-stream i R) + (integral (scale-stream i (/ 1 C)) v0 dt)))) + +#| 3.74 |# + +(define (sign-change-detector a b) + (cond + ((and (< a 0) (>= b 0)) 1) + ((and (>= a 0) (< b 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 sense-data) + (make-zero-crossings sense-data 0)) + +(#%provide zero-crossings-) +(define (zero-crossings- sense-data) + (stream-map- + sign-change-detector + sense-data + (stream-cdr sense-data))) + +#| 3.75 |# + +(#%provide make-zero-crossings-) +(define (make-zero-crossings- 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- + (stream-cdr input-stream) + (stream-car input-stream) + avpt)))) + +#| 3.76 |# + +(#%provide smooth) +(define (smooth stream) + (let + ((s0 (stream-ref stream 0)) + (s1 (stream-ref stream 1))) + (cons-stream + (average s0 s1) + (smooth (stream-cdr stream))))) + +(#%provide zero-crossings--) +(define (zero-crossings-- sense-data) + (let ((smoothed (smooth sense-data))) + (stream-map- + sign-change-detector + smoothed + (stream-cdr smoothed)))) + +;; Streams and Delayed Evaluation + +(#%provide integral-) +(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) + +(#%provide solve) +(define (solve f y0 dt) + (define y (integral- (delay (stream-map f y)) y0 dt)) + y) + +#| 3.77 |# + +(#%provide integral--) +(define (integral-- delayed-integrand initial-value dt) + (cons-stream + initial-value + (let ((integrand (force delayed-integrand))) + (if (stream-null? integrand) + the-empty-stream + (integral + (stream-cdr integrand) + (+ + (* dt (stream-car integrand)) + initial-value)))))) + +#| 3.78 |# + +(#%provide solve-2nd) +(define (solve-2nd a b dt y0 dy0) + (define ddy + #| (add-streams |# + #| (scale-stream dy a) |# + #| (scale-stream y b))) |# + (add-streams + (scale-stream (integral- (delay ddy) dy0 dt) a) + (scale-stream (integral- (delay (integral- (delay ddy) dy0 dt)) y0 dt) b))) + (define dy (integral- (delay ddy) dy0 dt)) + (define y (integral- (delay dy) y0 dt)) + y) + +#| 3.79 |# + +(#%provide solve-2nd-) +(define (solve-2nd- f dt y0 dy0) + (define ddy + #| (f dy y) |# + (f + (integral- (delay ddy) dy0 dt) + (integral- (delay (integral- (delay ddy) dy0 dt)) y0 dt))) + (define dy (integral- (delay ddy) dy0 dt)) + (define y (integral- (delay dy) y0 dt)) + y) + +#| 3.80 |# + +#| (#%provide RLC) |# +#| (define (RLC R L C dt) |# +#| (lambda (vc0 il0) |# +#| (define dil |# +#| (add-streams |# +#| (scale-stream vc (/ 1 L)) |# +#| (scale-stream il (- (/ R L))))) |# +#| (define dvc (scale-stream il (- (/ 1 C)))) |# +#| (define vc (integral- (delay dvc) vc0)) |# +#| (define il (integral- (delay dil) il0)) |# +#| (cons vc il))) |# + +;; Modularity of Functional Programs and Modularity of Objects + +(define random-init 4) + +(define (rand-update x) + (modulo (+ (* 75 x) 74) 65537)) + +(#%provide rand) +(define rand + (let ((x random-init)) + (lambda () + (set! x (rand-update x)) + x))) + +(#%provide random-numbers) +(define random-numbers + (cons-stream + random-init + (stream-map rand-update random-numbers))) + +(define (map-successive-pairs f s) + (cons-stream + (f (stream-car s) (stream-car (stream-cdr s))) + (map-successive-pairs f (stream-cdr (stream-cdr s))))) + +(#%provide cesaro-stream) +(define cesaro-stream + (map-successive-pairs + (lambda (r1 r2) (= (gcd r1 r2) 1)) + random-numbers)) + +(#%provide monte-carlo) +(define (monte-carlo experiment-stream passed failed) + (define (next passed failed) + (cons-stream + (/ passed (+ passed failed)) + (monte-carlo + (stream-cdr experiment-stream) passed failed))) + (if (stream-car experiment-stream) + (next (+ passed 1) failed) + (next passed (+ failed 1)))) + +(#%provide pi) +(define pi + (stream-map + (lambda (p) (sqrt (/ 6 p))) + (monte-carlo cesaro-stream 1 0))) + +#| 3.81 |# + +(#%provide rand-news) +(define (rand-news requests) + (define (next requests current) + (cond + ((eq? (stream-car requests) 'generate) + (cons-stream + current + (next + (stream-cdr requests) + (rand-update current)))) + ((eq? (stream-car requests) 'reset) + (cons-stream + (stream-car (stream-cdr requests)) + (next + (stream-cdr (stream-cdr requests)) + (rand-update (stream-car (stream-cdr requests)))))) + (else error "unknown symbol"))) + (next requests random-init)) + +#| 3.82 |# + +(define (random-in-range low high) + (let ((range (- high low))) + (+ low (random range)))) + +(define (random-points x1 x2 y1 y2) + (cons-stream + (list + (random-in-range x1 x2) + (random-in-range y1 y2)) + (random-points x1 x2 y1 y2))) + +(define (estimate-integral P x1 x2 y1 y2) + (monte-carlo + (stream-map + (lambda (xy) (apply P xy)) + (random-points x1 x2 y1 y2)) + 0 + 0)) + +(#%provide estimate-pi-integral) +(define estimate-pi-integral + (scale-stream + (estimate-integral + (lambda (x y) (<= (+ (square x) (square y)) 1.0)) + 0.0 1.0 + 0.0 1.0) + 4.0)) |