timothy235

sicp-3-5-3-exploiting-the-stream-paradigm

Mar 8th, 2017
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Racket 15.98 KB | None | 0 0
  1. #lang racket
  2. (require "3-5-streams.rkt")
  3.  
  4. (define (average a b)
  5.   (/ (+ a b) 2))
  6.  
  7. (define (sqrt-improve guess x)
  8.   (average guess (/ x guess)))
  9.  
  10. (define (sqrt-stream x)
  11.   (define guesses
  12.     (cons-stream 1.0
  13.                  (my-stream-map (lambda (guess)
  14.                                   (sqrt-improve guess x))
  15.                                 guesses)))
  16.   guesses)
  17.  
  18. ;; Should be: 1.4142135623730951
  19. (display-this-many 10 (sqrt-stream 2) 'vert)
  20. ;; 1.0
  21. ;; 1.5
  22. ;; 1.4166666666666665
  23. ;; 1.4142156862745097
  24. ;; 1.4142135623746899
  25. ;; 1.414213562373095
  26. ;; 1.414213562373095
  27. ;; 1.414213562373095
  28. ;; 1.414213562373095
  29. ;; 1.414213562373095
  30. ;; 'done
  31.  
  32. (define (pi-summands n)
  33.   (cons-stream (/ 1.0 n)
  34.                (my-stream-map - (pi-summands (+ n 2)))))
  35.  
  36. (define pi-stream
  37.   (scale-stream (partial-sums (pi-summands 1)) 4))
  38.  
  39. ;; Should be: 3.141592653589793
  40. (display-this-many 10 pi-stream 'vert)
  41. ;; 4.0
  42. ;; 2.666666666666667
  43. ;; 3.466666666666667
  44. ;; 2.8952380952380956
  45. ;; 3.3396825396825403
  46. ;; 2.9760461760461765
  47. ;; 3.2837384837384844
  48. ;; 3.017071817071818
  49. ;; 3.2523659347188767
  50. ;; 3.0418396189294032
  51. ;; 'done
  52.  
  53. (define (euler-transform s)
  54.   (define s0 (my-stream-ref s 0))
  55.   (define s1 (my-stream-ref s 1))
  56.   (define s2 (my-stream-ref s 2))
  57.   (cons-stream (- s2 (/ (sqr (- s2 s1))
  58.                         (+ s0 (* -2 s1) s2)))
  59.                (euler-transform (stream-cdr s))))
  60.  
  61. ;; Should be: 3.141592653589793
  62. (display-this-many 10 (euler-transform pi-stream) 'vert)
  63. ;; 3.166666666666667
  64. ;; 3.1333333333333337
  65. ;; 3.1452380952380956
  66. ;; 3.13968253968254
  67. ;; 3.1427128427128435
  68. ;; 3.1408813408813416
  69. ;; 3.142071817071818
  70. ;; 3.1412548236077655
  71. ;; 3.1418396189294033
  72. ;; 3.141406718496503
  73. ;; 'done
  74.  
  75. (define (make-tableau transform s)
  76.   (cons-stream s
  77.                (make-tableau transform
  78.                              (transform s))))
  79.  
  80. (define (accelerated-sequence transform s)
  81.   (my-stream-map stream-car
  82.                  (make-tableau transform s)))
  83.  
  84. ;; Should be: 3.141592653589793
  85. (display-this-many 10 (accelerated-sequence euler-transform pi-stream) 'vert)
  86. ;; 4.0
  87. ;; 3.166666666666667
  88. ;; 3.142105263157895
  89. ;; 3.141599357319005
  90. ;; 3.1415927140337785
  91. ;; 3.1415926539752927
  92. ;; 3.1415926535911765
  93. ;; 3.141592653589778
  94. ;; 3.1415926535897953
  95. ;; 3.141592653589795
  96. ;; 'done
  97.  
  98. ;;;;;;;;;;
  99. ;; 3.63 ;;
  100. ;;;;;;;;;;
  101.  
  102. (define (slow-sqrt-stream x)
  103.   (cons-stream 1.0
  104.                (my-stream-map (lambda (guess)
  105.                                 (sqrt-improve guess x))
  106.                               (slow-sqrt-stream x))))
  107.  
  108. ;; Recursing on sqrt-stream, instead of using the local variable guesses,
  109. ;; repeatedly creates new streams whose elements have not been forced and cached
  110. ;; yet.  So you lose the benefits of caching.  If you were using un-memoized
  111. ;; streams, there would be no difference.
  112.  
  113. (time (my-stream-ref (sqrt-stream 2) 100))
  114. ;; cpu time: 0 real time: 0 gc time: 0
  115. ;; 1.414213562373095
  116. (time (my-stream-ref (slow-sqrt-stream 2) 100))
  117. ;; cpu time: 16 real time: 9 gc time: 0
  118. ;; 1.414213562373095
  119.  
  120. (time (my-stream-ref (sqrt-stream 2) 1000))
  121. ;; cpu time: 0 real time: 1 gc time: 0
  122. ;; 1.414213562373095
  123. (time (my-stream-ref (slow-sqrt-stream 2) 1000))
  124. ;; cpu time: 703 real time: 841 gc time: 312
  125. ;; 1.414213562373095
  126.  
  127. ;;;;;;;;;;
  128. ;; 3.64 ;;
  129. ;;;;;;;;;;
  130.  
  131. (define (stream-limit s tolerance)
  132.   (define (loop s1 s2 str)
  133.     (if (< (abs (- s1 s2)) tolerance)
  134.       s2
  135.       (loop s2 (stream-car str) (stream-cdr str))))
  136.   (loop (stream-car s)
  137.         (stream-car (stream-cdr s))
  138.         (stream-cdr (stream-cdr s))))
  139.  
  140. ;;;;;;;;;;
  141. ;; 3.65 ;;
  142. ;;;;;;;;;;
  143.  
  144. (define (ln2-summands n)
  145.   (cons-stream (/ 1.0 n)
  146.                (my-stream-map - (ln2-summands (add1 n)))))
  147.  
  148. (display-this-many 10 (ln2-summands 1) 'vert)
  149. ;; 1.0
  150. ;; -0.5
  151. ;; 0.3333333333333333
  152. ;; -0.25
  153. ;; 0.2
  154. ;; -0.16666666666666666
  155. ;; 0.14285714285714285
  156. ;; -0.125
  157. ;; 0.1111111111111111
  158. ;; -0.1
  159. ;; 'done
  160.  
  161. ;; Actual value: ln 2 = 0.6931471805599453
  162.  
  163. (define ln2-stream1 (partial-sums (ln2-summands 1)))
  164. (time (stream-limit ln2-stream1 0.001))
  165. ;; cpu time: 1531 real time: 1536 gc time: 766
  166. ;; 0.6936464315588232
  167.  
  168. (define ln2-stream2 (euler-transform ln2-stream1))
  169. (time (stream-limit ln2-stream2 0.001))
  170. ;; cpu time: 0 real time: 0 gc time: 0
  171. ;; 0.6928571428571428
  172.  
  173. (define ln2-stream3 (accelerated-sequence euler-transform ln2-stream1))
  174. (time (stream-limit ln2-stream3 0.001))
  175. ;; cpu time: 0 real time: 0 gc time: 0
  176. ;; 0.6931488693329254
  177.  
  178. ;; Now let's compare the fast streams.
  179.  
  180. ;; the euler transform
  181. (time (stream-limit ln2-stream2 0.000000001)) ; tolerance is 10 ^ -9
  182. ;; cpu time: 609 real time: 618 gc time: 330
  183. ;; 0.6931471810586626
  184.  
  185. ;; the accelerated sequence
  186. (time (stream-limit ln2-stream3 0.000000001))
  187. ;; cpu time: 0 real time: 0 gc time: 0
  188. ;; 0.6931471805604039
  189.  
  190. ;; So the transforms really speed things up.
  191.  
  192. ;;;;;;;;;;
  193. ;; 3.66 ;;
  194. ;;;;;;;;;;
  195.  
  196. (define (interleave s1 s2)
  197.   (if (stream-null? s1)
  198.     s2
  199.     (cons-stream (stream-car s1)
  200.                  (interleave s2 (stream-cdr s1)))))
  201.  
  202. (define (pairs s t)
  203.   (cons-stream
  204.     (list (stream-car s) (stream-car t))
  205.     (interleave
  206.       (my-stream-map (lambda (x) (list (stream-car s) x))
  207.                   (stream-cdr t))
  208.       (pairs (stream-cdr s) (stream-cdr t)))))
  209.  
  210. (define prs (pairs integers integers))
  211.  
  212. (display-this-many 10 prs)
  213. ;; (1 1) (1 2) (2 2) (1 3) (2 3) (1 4) (3 3) (1 5) (2 4) (1 6)
  214. ;; 'done
  215.  
  216. ;; Let's gather some data on how these elements are arranged in the sequence of
  217. ;; pairs.
  218.  
  219. (define (how-many-precede s elt)
  220.   (define (loop i str)
  221.     (if (equal? (stream-car str) elt)
  222.       i
  223.       (loop (add1 i) (stream-cdr str))))
  224.   (loop 0 s))
  225.  
  226. ;; How many precede (n, n)?
  227. ;; Answer: 2 ^ n - 2.
  228. (for ([i (in-range 1 11)])
  229.   (define pr (list i i))
  230.   (printf "~a ~a ~n" pr (how-many-precede prs pr)))
  231. ;; (1 1) 0
  232. ;; (2 2) 2
  233. ;; (3 3) 6
  234. ;; (4 4) 14
  235. ;; (5 5) 30
  236. ;; (6 6) 62
  237. ;; (7 7) 126
  238. ;; (8 8) 254
  239. ;; (9 9) 510
  240. ;; (10 10) 1022
  241.  
  242. ;; How many precede (n, n + 1)?
  243. ;; Answer: 2 ^ (n - 1) more than precede (n, n).
  244. (for ([i (in-range 1 11)])
  245.   (define pr (list i (add1 i)))
  246.   (printf "~a ~a ~n" pr (how-many-precede prs pr)))
  247. ;; (1 2) 1
  248. ;; (2 3) 4
  249. ;; (3 4) 10
  250. ;; (4 5) 22
  251. ;; (5 6) 46
  252. ;; (6 7) 94
  253. ;; (7 8) 190
  254. ;; (8 9) 382
  255. ;; (9 10) 766
  256. ;; (10 11) 1534
  257.  
  258. ;; How many precede (n, n + 2)?
  259. ;; Answer: 2 ^ n more than precede (n, n + 1).
  260. (for ([i (in-range 1 11)])
  261.   (define pr (list i (+ i 2)))
  262.   (printf "~a ~a ~n" pr (how-many-precede prs pr)))
  263. ;; (1 3) 3
  264. ;; (2 4) 8
  265. ;; (3 5) 18
  266. ;; (4 6) 38
  267. ;; (5 7) 78
  268. ;; (6 8) 158
  269. ;; (7 9) 318
  270. ;; (8 10) 638
  271. ;; (9 11) 1278
  272. ;; (10 12) 2558
  273.  
  274. ;; So the number of elements preceding an element (n, k) will be:
  275.  
  276. ;; 2 ^ n - 2 if k = n
  277. ;; 2 ^ n - 2 + 2 ^ (n - 1) if k = n + 1
  278. ;; 2 ^ n - 2 + 2 ^ (n - 1) + (k - n - 1) * 2 ^ n if k > n + 1
  279.  
  280. ;; # elements preceding (1, 100) = 2 ^ 1 - 2 + 2 ^ 0 + 98 * 2 ^ 1 = 197
  281. ;; # elements preceding (99, 100) = 2 ^ 99 - 2 + 2 ^ 98
  282.     ;; = 950737950171172051122527404030
  283. ;; # elements preceding (100, 100) = 2 ^ 100 - 2
  284.     ;; = 1267650600228229401496703205374
  285.  
  286. (how-many-precede prs '(1 100))
  287. ;; 197
  288.  
  289. ;;;;;;;;;;
  290. ;; 3.67 ;;
  291. ;;;;;;;;;;
  292.  
  293. ;; The idea is to take out the corner element, and then interleave the top row,
  294. ;; the first column, and a recursive call to all-pairs.
  295.  
  296. (define (all-pairs s t)
  297.   (cons-stream
  298.     (list (stream-car s) (stream-car t))
  299.     (interleave (my-stream-map (lambda (x) (list (stream-car s) x))
  300.                                (stream-cdr t))
  301.                 (interleave (my-stream-map (lambda (x) (list x (stream-car t)))
  302.                                            (stream-cdr s))
  303.                             (all-pairs (stream-cdr s) (stream-cdr t))))))
  304.  
  305. (define all-prs (all-pairs integers integers))
  306.  
  307. (display-this-many 10 all-prs 'vert)
  308. ;; (1 1)
  309. ;; (1 2)
  310. ;; (2 1)
  311. ;; (1 3)
  312. ;; (2 2)
  313. ;; (1 4)
  314. ;; (3 1)
  315. ;; (1 5)
  316. ;; (2 3)
  317. ;; (1 6)
  318. ;; 'done
  319.  
  320. ;;;;;;;;;;
  321. ;; 3.68 ;;
  322. ;;;;;;;;;;
  323.  
  324. (define (bad-pairs s t)
  325.   (interleave
  326.     (my-stream-map (lambda (x) (list (stream-car s) x))
  327.                    t)
  328.     (bad-pairs (stream-cdr s) (stream-cdr t))))
  329.  
  330. ;; Evaluating (bad-pairs s t) requires evaluating
  331. ;; (bad-pairs (stream-cdr s) (stream-cdr t)), which has the same problem
  332. ;; with its own recursive call, and we fall immediately into an infinite loop.
  333. ;; This is because of eager evaluation.  Even though interleave uses the
  334. ;; stream-car of the first parameter as its own stream-car, eager evaluation
  335. ;; requires the computation of the stream-car of both parameters.
  336.  
  337. ;; In general, when defining a stream, you cannot make a recursive call to get the
  338. ;; stream-car, only the stream-cdr.
  339.  
  340. ;;;;;;;;;;
  341. ;; 3.69 ;;
  342. ;;;;;;;;;;
  343.  
  344. (define (triples s t u)
  345.   (define ps (pairs t u))
  346.   (cons-stream (list (stream-car s)
  347.                      (stream-car t)
  348.                      (stream-car u))
  349.                (interleave (my-stream-map (lambda (p)
  350.                                          (cons (stream-car s) p))
  351.                                        (stream-cdr (pairs t u)))
  352.                            (triples (stream-cdr s)
  353.                                     (stream-cdr t)
  354.                                     (stream-cdr u)))))
  355.  
  356. (define trpls (triples integers integers integers))
  357.  
  358. (display-this-many 10 trpls 'vert)
  359. ;; (1 1 1)
  360. ;; (1 1 2)
  361. ;; (2 2 2)
  362. ;; (1 2 2)
  363. ;; (2 2 3)
  364. ;; (1 1 3)
  365. ;; (3 3 3)
  366. ;; (1 2 3)
  367. ;; (2 3 3)
  368. ;; (1 1 4)
  369. ;; 'done
  370.  
  371. (define (pythagorean? triple)
  372.   (= (+ (sqr (first triple))
  373.         (sqr (second triple)))
  374.      (sqr (third triple))))
  375.  
  376. (define pythagorean-triples (my-stream-filter pythagorean? trpls))
  377.  
  378.  
  379. ;; It will take a very long time to produce more than six of these.
  380. (display-this-many 4 pythagorean-triples 'vert)
  381. ;; (3 4 5)
  382. ;; (6 8 10)
  383. ;; (5 12 13)
  384. ;; (9 12 15)
  385. ;; 'done
  386.  
  387. ;;;;;;;;;;
  388. ;; 3.70 ;;
  389. ;;;;;;;;;;
  390.  
  391. (define (merge-weighted weight ps1 ps2)
  392.   (define p1 (stream-car ps1))
  393.   (define p2 (stream-car ps2))
  394.   (if (> (weight p1) (weight p2))
  395.     (cons-stream p2
  396.                  (merge-weighted weight
  397.                                  ps1
  398.                                  (stream-cdr ps2)))
  399.     (cons-stream p1
  400.                  (merge-weighted weight
  401.                                  (stream-cdr ps1)
  402.                                  ps2))))
  403.  
  404. (define (weighted-pairs weight s t)
  405.   (cons-stream (list (stream-car s)
  406.                      (stream-car t))
  407.                (merge-weighted weight
  408.                                (my-stream-map (lambda (x) (list (stream-car s) x))
  409.                                               (stream-cdr t))
  410.                                (weighted-pairs weight
  411.                                                (stream-cdr s)
  412.                                                (stream-cdr t)))))
  413.  
  414. (define (weight1 pr) (+ (first pr) (second pr)))
  415.  
  416. (define st1 (weighted-pairs weight1 integers integers))
  417.  
  418. (display-this-many 10 st1 'vert)
  419. ;; (1 1)
  420. ;; (1 2)
  421. ;; (1 3)
  422. ;; (2 2)
  423. ;; (1 4)
  424. ;; (2 3)
  425. ;; (1 5)
  426. ;; (2 4)
  427. ;; (3 3)
  428. ;; (1 6)
  429. ;; 'done
  430.  
  431. (define (not-div-2-3-5? a)
  432.   (and (not (zero? (remainder a 2)))
  433.        (not (zero? (remainder a 3)))
  434.        (not (zero? (remainder a 5)))))
  435.  
  436. (define (weight2 pr) (+ (* 2 (first pr))
  437.                         (* 3 (second pr))
  438.                         (* 5 (first pr) (second pr))))
  439.  
  440. (define st2 (weighted-pairs
  441.               weight2
  442.               (my-stream-filter not-div-2-3-5? integers)
  443.               (my-stream-filter not-div-2-3-5? integers)))
  444.  
  445. (display-this-many 10 st2 'vert)
  446. ;; (1 1)
  447. ;; (1 7)
  448. ;; (1 11)
  449. ;; (1 13)
  450. ;; (1 17)
  451. ;; (1 19)
  452. ;; (1 23)
  453. ;; (1 29)
  454. ;; (1 31)
  455. ;; (7 7)
  456. ;; 'done
  457.  
  458. ;;;;;;;;;;
  459. ;; 3.71 ;;
  460. ;;;;;;;;;;
  461.  
  462. (define (generalized-ramanujan f n)
  463.   ;; Generate all positive numbers that can be written as f(i, j) for 0 < i < j
  464.   ;; in n different ways, n > 1, alongwith the corresponding n-tuples.
  465.   (define (tuples s)
  466.     ; Break s into n-tuples.
  467.     (define (loop i lst str)
  468.       (if (> i n)
  469.         (reverse lst)
  470.         (loop (add1 i)
  471.               (cons (stream-car str) lst)
  472.               (stream-cdr str))))
  473.     (cons-stream (loop 1 empty s)
  474.                  (tuples (stream-cdr s))))
  475.   (define (good-tuple? tuple)
  476.     (define val (f (first tuple)))
  477.     (for/and ([i (in-range 1 n)])
  478.              (= (f (list-ref tuple i)) val)))
  479.   (my-stream-map
  480.     (lambda (tuple) (cons (f (first tuple)) tuple))
  481.     (my-stream-filter good-tuple?
  482.                       (tuples (weighted-pairs f
  483.                                               integers
  484.                                               integers)))))
  485.  
  486. (define (sum-of-cubes pr)
  487.   (+ (expt (first pr) 3)
  488.      (expt (second pr) 3)))
  489.  
  490. (define ramanujan (generalized-ramanujan sum-of-cubes 2))
  491.  
  492. (display-this-many 10 ramanujan 'vert)
  493. ;; (1729 (1 12) (9 10))
  494. ;; (4104 (2 16) (9 15))
  495. ;; (13832 (2 24) (18 20))
  496. ;; (20683 (10 27) (19 24))
  497. ;; (32832 (4 32) (18 30))
  498. ;; (39312 (2 34) (15 33))
  499. ;; (40033 (9 34) (16 33))
  500. ;; (46683 (3 36) (27 30))
  501. ;; (64232 (17 39) (26 36))
  502. ;; (65728 (12 40) (31 33))
  503. ;; 'done
  504.  
  505. ;;;;;;;;;;
  506. ;; 3.72 ;;
  507. ;;;;;;;;;;
  508.  
  509. (define (sum-of-squares pr)
  510.   (+ (sqr (first pr))
  511.      (sqr (second pr))))
  512.  
  513. (define sum-of-two-squares-in-three-ways
  514.   (generalized-ramanujan sum-of-squares 3))
  515.  
  516. (display-this-many 10 sum-of-two-squares-in-three-ways 'vert)
  517. ;; (325 (1 18) (6 17) (10 15))
  518. ;; (425 (5 20) (8 19) (13 16))
  519. ;; (650 (5 25) (11 23) (17 19))
  520. ;; (725 (7 26) (10 25) (14 23))
  521. ;; (845 (2 29) (13 26) (19 22))
  522. ;; (850 (3 29) (11 27) (15 25))
  523. ;; (925 (5 30) (14 27) (21 22))
  524. ;; (1025 (1 32) (8 31) (20 25))
  525. ;; (1105 (4 33) (9 32) (12 31))
  526. ;; (1105 (9 32) (12 31) (23 24))
  527. ;; 'done
  528.  
  529. ;;;;;;;;;;
  530. ;; 3.73 ;;
  531. ;;;;;;;;;;
  532.  
  533. (define (integral integrand initial-value dt)
  534.   (define int
  535.     (cons-stream initial-value
  536.                  (add-streams (scale-stream integrand dt)
  537.                               int)))
  538.   int)
  539.  
  540. (define (RC R C dt)
  541.   (lambda (i v0)
  542.     (add-streams (scale-stream (integral i v0 dt)
  543.                                (/ 1.0 C))
  544.                  (scale-stream i R))))
  545.  
  546. (define RC1 (RC 5 1 0.5))
  547.  
  548. (display-this-many 10 (RC1 ones 2) 'vert)
  549. ;; 7.0
  550. ;; 7.5
  551. ;; 8.0
  552. ;; 8.5
  553. ;; 9.0
  554. ;; 9.5
  555. ;; 10.0
  556. ;; 10.5
  557. ;; 11.0
  558. ;; 11.5
  559. ;; 'done
  560.  
  561. ;;;;;;;;;;
  562. ;; 3.74 ;;
  563. ;;;;;;;;;;
  564.  
  565. (define (sign-change-detector current lastval)
  566.   (cond [(and (negative? lastval) (>= current 0)) 1]
  567.         [(and (>= lastval 0) (negative? current)) -1]
  568.         [else 0]))
  569.  
  570. (define (get-next current)
  571.   ; get test data by cycling from -2 up to 2 and repeating
  572.   (if (= current 2)
  573.     -2
  574.     (add1 current)))
  575.  
  576. (define sense-data
  577.   (cons-stream 1 (my-stream-map get-next sense-data)))
  578.  
  579. (define zero-crossings
  580.   (my-stream-map sign-change-detector
  581.                  sense-data
  582.                  (cons-stream 0 sense-data)))
  583.  
  584. (display-this-many 10 sense-data)
  585. ;; 1 2 -2 -1 0 1 2 -2 -1 0
  586. ;; 'done
  587.  
  588. (display-this-many 10 zero-crossings)
  589. ;; 0 0 -1 0 1 0 0 -1 0 1
  590. ;; 'done
  591.  
  592. ;;;;;;;;;;
  593. ;; 3.75 ;;
  594. ;;;;;;;;;;
  595.  
  596. ;; The original version kept averaging in the average value, so avpt was no longer
  597. ;; the average of the next two stream elements.
  598.  
  599. (define (make-zero-crossings input-stream last-value last-avpt)
  600.   (define avpt (average (stream-car input-stream) last-value))
  601.   (cons-stream (sign-change-detector avpt last-avpt)
  602.                (make-zero-crossings (stream-cdr input-stream)
  603.                                     (stream-car input-stream)
  604.                                     avpt)))
  605.  
  606. (display-this-many 10 (make-zero-crossings sense-data 0 0))
  607. ;; 0 0 0 -1 0 1 0 0 -1 0
  608. ;; 'done
  609.  
  610. ;;;;;;;;;;
  611. ;; 3.76 ;;
  612. ;;;;;;;;;;
  613.  
  614. (define (smooth input-stream)
  615.   (my-stream-map average
  616.                  input-stream
  617.                  (cons-stream 0 input-stream)))
  618.  
  619. (define (new-make-zero-crossings input-stream)
  620.   (define smoothed-stream (smooth input-stream))
  621.   (my-stream-map sign-change-detector
  622.                  smoothed-stream
  623.                  (cons-stream 0 smoothed-stream)))
  624.  
  625. (display-this-many 10 (new-make-zero-crossings sense-data))
  626. ;; 0 0 0 -1 0 1 0 0 -1 0
  627. ;; 'done
Add Comment
Please, Sign In to add comment