timothy235

sicp-3-5-streams

Mar 6th, 2017
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Racket 7.57 KB | None | 0 0
  1. #lang racket
  2. (require rackunit) ; for check-equal?
  3. (provide (all-defined-out))
  4.  
  5. ;; The book code and examples from sections 3.5.1 and 3.5.2.
  6.  
  7. ;; Racket has built-in streams, but this is the book implementation.  Use
  8. ;; define-syntax-rule to create the new special forms my-delay and cons-stream.
  9.  
  10. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  11. ;; 3.5.1 STREAM IMPLEMENTATION AND PROCEDURES ;;
  12. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  13.  
  14. (define (memo-proc proc)
  15.   (define already-run? false)
  16.   (define result false)
  17.   (lambda ()
  18.     (cond [(not already-run?)
  19.            (set! result (proc))
  20.            (set! already-run? true)
  21.            result]
  22.           [else result])))
  23.  
  24. (define-syntax-rule (my-delay e) (memo-proc (lambda () e)))
  25. (define (my-force delayed-object) (delayed-object))
  26.  
  27. (define (stream-car s) (car s))
  28. (define (stream-cdr s) (my-force (cdr s)))
  29.  
  30. ;; Use this definition of cons-stream for memoized streams.
  31. (define-syntax-rule (cons-stream a b) (cons a (my-delay b)))
  32.  
  33. ;; ;; Use this definition of cons-stream for un-memoized streams.
  34. ;; (define-syntax-rule (no-memo-delay e) (lambda () e))
  35. ;; (define-syntax-rule (cons-stream a b) (cons a (no-memo-delay b)))
  36.  
  37. (define the-empty-stream empty)
  38. (define stream-null? empty?)
  39.  
  40. (define (my-stream-ref s n)
  41.   (if (zero? n)
  42.     (stream-car s)
  43.     (my-stream-ref (stream-cdr s) (sub1 n))))
  44.  
  45. (define (my-stream-map proc . argstreams)
  46.   ; the generalized version from exercise 3.50
  47.   (if (stream-null? (car argstreams))
  48.     the-empty-stream
  49.     (cons-stream (apply proc (map stream-car argstreams))
  50.                  (apply my-stream-map
  51.                         (cons proc (map stream-cdr argstreams))))))
  52.  
  53. (define (my-stream-filter pred s)
  54.   (cond [(stream-null? s) the-empty-stream]
  55.         [(pred (stream-car s))
  56.          (cons-stream (stream-car s)
  57.                       (my-stream-filter pred (stream-cdr s)))]
  58.         [else (my-stream-filter pred (stream-cdr s))]))
  59.  
  60. (define (my-stream-for-each proc s)
  61.   (cond [(stream-null? s) 'done]
  62.         [else (proc (stream-car s))
  63.               (my-stream-for-each proc (stream-cdr s))]))
  64.  
  65. (define (display-stream s) (my-stream-for-each displayln s))
  66.  
  67. (define (stream-enumerate-interval low high)
  68.   (if (> low high)
  69.     the-empty-stream
  70.     (cons-stream low
  71.                  (stream-enumerate-interval (add1 low) high))))
  72.  
  73. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  74. ;; 3.5.2 EXAMPLES AND MORE STREAM PROCEDURES ;;
  75. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  76.  
  77. (define (integers-starting-from n)
  78.   (cons-stream n (integers-starting-from (add1 n))))
  79. (define integers1 (integers-starting-from 1))
  80.  
  81. (define (divisible? x y) (zero? (remainder x y)))
  82. (define no-sevens (my-stream-filter (lambda (x) (not (divisible? x 7)))
  83.                                     integers1))
  84.  
  85. (define (fibgen a b)
  86.   (cons-stream a (fibgen b (+ a b))))
  87. (define fibs1 (fibgen 0 1))
  88.  
  89. (define (sieve s)
  90.   (cons-stream
  91.     (stream-car s)
  92.     (sieve (my-stream-filter
  93.              (lambda (x)
  94.                (not (divisible? x (stream-car s))))
  95.              (stream-cdr s)))))
  96. (define primes1 (sieve (integers-starting-from 2)))
  97.  
  98. (define ones (cons-stream 1 ones))
  99.  
  100. (define (add-streams s1 s2)
  101.   (my-stream-map + s1 s2))
  102. (define integers (cons-stream 1 (add-streams ones integers)))
  103.  
  104. (define fibs
  105.   (cons-stream 0
  106.                (cons-stream 1
  107.                             (add-streams (stream-cdr fibs)
  108.                                          fibs))))
  109.  
  110. (define (scale-stream s factor)
  111.   (my-stream-map (lambda (x) (* x factor)) s))
  112.  
  113. (define double (cons-stream 1 (scale-stream double 2)))
  114.  
  115. (define primes
  116.   (cons-stream
  117.     2
  118.     (my-stream-filter prime? (integers-starting-from 3))))
  119.  
  120. (define (prime? n)
  121.   (define (iter ps)
  122.     (cond [(> (sqr (stream-car ps)) n) true]
  123.           [(divisible? n (stream-car ps)) false]
  124.           [else (iter (stream-cdr ps))]))
  125.   (iter primes))
  126.  
  127. ;; PROCEDURES FROM THE 3.5.2 EXERCISES
  128.  
  129. (define (mul-streams s1 s2)
  130.   (my-stream-map * s1 s2))
  131.  
  132. (define factorials
  133.   (cons-stream 1
  134.                (mul-streams factorials integers)))
  135.  
  136. (define (partial-sums s)
  137.   (cons-stream (stream-car s)
  138.                (add-streams (stream-cdr s)
  139.                             (partial-sums s))))
  140.  
  141. (define (merge s1 s2)
  142.   (cond [(stream-null? s1) s2]
  143.         [(stream-null? s2) s1]
  144.         [else
  145.           (define s1car (stream-car s1))
  146.           (define s2car (stream-car s2))
  147.           (cond [(< s1car s2car)
  148.                  (cons-stream s1car (merge (stream-cdr s1) s2))]
  149.                 [(> s1car s2car)
  150.                  (cons-stream s2car (merge s1 (stream-cdr s2)))]
  151.                 [else
  152.                   (cons-stream s1car
  153.                                (merge (stream-cdr s1)
  154.                                       (stream-cdr s2)))])]))
  155.  
  156. (define hamming
  157.   (cons-stream 1
  158.                (merge (scale-stream hamming 2)
  159.                       (merge (scale-stream hamming 3)
  160.                              (scale-stream hamming 5)))))
  161.  
  162. (define (expand num den radix)
  163.   (cons-stream
  164.     (quotient (* num radix) den)
  165.     (expand (remainder (* num radix) den) den radix)))
  166.  
  167. (define (integrate-series s)
  168.   (my-stream-map / s integers))
  169.  
  170. (define exp-series
  171.   (cons-stream 1 (integrate-series exp-series)))
  172.  
  173. (define cosine-series ; derivative of cosine is -1 * sine
  174.   (cons-stream 1 (scale-stream
  175.                    (integrate-series sine-series)
  176.                    -1)))
  177.  
  178. (define sine-series ; derivative of sine is cosine
  179.   (cons-stream 0 (integrate-series cosine-series)))
  180.  
  181. (define (mul-series s1 s2)
  182.   (cons-stream (* (stream-car s1)
  183.                   (stream-car s2))
  184.                (add-streams (scale-stream (stream-cdr s2) (stream-car s1))
  185.                             (mul-series s2 (stream-cdr s1)))))
  186.  
  187. (define (invert-unit-series s)
  188.   (unless (= (stream-car s) 1)
  189.     (error "Constant term must be 1 -- INVERT-UNIT-SERIES" s))
  190.   (cons-stream 1
  191.                (scale-stream (mul-series (stream-cdr s)
  192.                                          (invert-unit-series s))
  193.                              -1)))
  194.  
  195. (define (div-series s1 s2)
  196.   (when (zero? (stream-car s2))
  197.     (error "Constant term of second series must be non-zero -- DIV-SERIES" s2))
  198.   (scale-stream
  199.     (mul-series s1
  200.                 (invert-unit-series (scale-stream s2
  201.                                                   (/ 1 (stream-car s2)))))
  202.     (stream-car s2)))
  203.  
  204. (define tangent-series (div-series sine-series cosine-series))
  205.  
  206. (define (display-this-many n s [direction 'horiz])
  207.   (define (loop i st)
  208.     (cond [(eq? direction 'horiz)
  209.            (printf "~a " (stream-car st))
  210.            (if (= i n)
  211.              (printf "~n")
  212.              (loop (add1 i) (stream-cdr st)))]
  213.           [(eq? direction 'vert)
  214.            (printf "~a ~n" (stream-car st))
  215.            (unless (= i n) (loop (add1 i) (stream-cdr st)))]
  216.           [else (error "Unknown direction -- DISPLAY-THIS-MANY" direction)]))
  217.   (loop 1 s)
  218.   'done)
  219.  
  220. ;;;;;;;;;;;
  221. ;; TESTS ;;
  222. ;;;;;;;;;;;
  223.  
  224. (check-equal? (my-stream-ref integers1 1000) 1001)
  225. (check-equal? (my-stream-ref no-sevens 100) 117)
  226. (check-equal? (my-stream-ref fibs1 25) 75025)
  227. (check-equal? (my-stream-ref primes1 50) 233)
  228. (check-equal? (my-stream-ref integers 1000) 1001)
  229. (check-equal? (my-stream-ref fibs 25) 75025)
  230. (check-equal? (my-stream-ref double 10) 1024)
  231. (check-equal? (my-stream-ref primes 50) 233)
  232. (check-equal? (my-stream-ref factorials 9) 362880)
  233. (check-equal? (my-stream-ref (partial-sums integers) 9) 55)
  234. (check-equal? (my-stream-ref hamming 9) 12)
  235. (check-equal? (my-stream-ref tangent-series 7) (/ 17 315))
Add Comment
Please, Sign In to add comment