; rosettacode.org/wiki/Sieve_of_Eratosthenes#Scheme
; rosettacode.org/wiki/Sieve_of_Eratosthenes#Using_SICP-style_streams
;;;; Stream Implementation
(define (head s) (car s))
(define (tail s) ((cdr s)))
;;;; Stream Utility Functions
(define (from-By x s)
(cons x (lambda () (from-By (+ x s) s))))
(define (take n s)
(cond
((> n 1) (cons (head s) (take (- n 1) (tail s))))
((= n 1) (list (head s))) ;; don't force it too soon!!
(else '()))) ;; so (take 4 (s-map / (from-By 4 -1))) works
(define (drop n s)
(cond
((> n 0) (drop (- n 1) (tail s)))
(else s)))
(define (s-map f s)
(cons (f (head s)) (lambda () (s-map f (tail s)))))
(define (s-diff s1 s2)
(let ((h1 (head s1)) (h2 (head s2)))
(cond
((< h1 h2) (cons h1 (lambda () (s-diff (tail s1) s2 ))))
((< h2 h1) (s-diff s1 (tail s2)) )
(else (s-diff (tail s1) (tail s2)) ))))
(define (s-union s1 s2)
(let ((h1 (head s1)) (h2 (head s2)))
(cond
((< h1 h2) (cons h1 (lambda () (s-union (tail s1) s2 ))))
((< h2 h1) (cons h2 (lambda () (s-union s1 (tail s2)))))
(else (cons h1 (lambda () (s-union (tail s1) (tail s2))))))))
;;;; all primes' multiples are removed, merged through a tree of unions
;;;; runs in ~ n^1.2 run time in producing n = 2k... 4k primes in Guile(ideone)
(define (primes-stream)
(letrec ( (mults (lambda (p) (from-By (* p p) (* 2 p))))
(no-mults-From (lambda (from)
(s-diff (from-By from 2)
(s-tree-join (s-map mults odd-primes)))))
(odd-primes ;; inner feedback loop
(cons 3 (lambda () (no-mults-From 5)))) )
(cons 2 (lambda () (no-mults-From 3))))) ;; result stream
;;;; join an ordered stream of streams (here, of primes' multiples)
;;;; into one ordered stream, via an infinite right-deepening tree
(define (s-tree-join sts)
(cons (head (head sts))
(lambda ()
(s-union (tail (head sts))
(s-tree-join (pairs (tail sts)))))))
(define (pairs sts) ;; {a.(b.t)} -> (a+b).{t}
(cons (cons (head (head sts))
(lambda ()
(s-union (tail (head sts))
(head (tail sts)))))
(lambda ()
(pairs (tail (tail sts))))))
(display (take 2 (drop (- 4000 1) (primes-stream))))