(define (factorial-stream)
(define (helper factorial factor)
(let ((next-factorial (* factorial factor))
(next-factor (+ 1 factor)))
(cons-stream next-factorial (helper next-factorial next-factor))))
(helper 1 1))
(define (quotient-stream numerator denominator-stream)
(if (null? denominator-stream)
denominator-stream
(cons-stream (quotient numerator (head denominator-stream))
(quotient-stream numerator (tail denominator-stream)))))
(define (e-stream max-number-of-digits)
(let ((one (expt 10 (+ max-number-of-digits 1))))
(define (helper e digit fquotients)
(if (> digit max-number-of-digits)
'()
(let ((digit-magnitude (/ one (expt 10 (- digit 1))))
(fquotient (head fquotients)))
(if (> (quotient digit-magnitude fquotient) 100)
(cons-stream (quotient e digit-magnitude)
(helper (remainder e digit-magnitude) (+ 1 digit) fquotients))
(helper (+ e fquotient) digit (tail fquotients))))))
(helper one 1 (quotient-stream one (factorial-stream)))))
(define (ten-consecutive-digits-stream stream)
(n-consecutive-digits-stream 10 stream))
(define (n-consecutive-digits-stream n stream)
(define (helper stream lizt)
(cons-stream (list-to-number lizt)
(helper (tail stream) (append (cdr lizt) (list (head stream))))))
(helper (nthtail n stream) (stream-to-list stream n)))
(define (stream-to-list stream number-of-elements)
(define (iterate stream number-of-elements list)
(if (zero? number-of-elements)
list
(iterate (tail stream) (- number-of-elements 1) (cons (head stream) list))))
(reverse (iterate stream number-of-elements '())))
(define (list-to-number list)
(reduce (lambda (x y) (+ (* x 10) y)) 0 list))
(define (nthtail n stream)
(if (zero? n)
stream
(nthtail (- n 1) (tail stream))))
(define (sum-49? number)
(sum-n? 49 number))
(define (sum-n? n number)
(= n (sum-digits number)))
(define (sum-digits n)
(define (helper qtient sum)
(if (zero? qtient)
sum
(helper (quotient qtient 10) (+ sum (remainder qtient 10)))))
(helper n 0))
(define (prime? n)
(define (square x) (* x x))
(define (divides? a b)
(= (remainder b a) 0))
(define (find-divisor n test-divisor)
(cond ((> (square test-divisor) n) n)
((divides? test-divisor n) test-divisor)
(else (find-divisor n (+ test-divisor 1)))))
(define (smallest-divisor n)
(find-divisor n 2))
(= n (smallest-divisor n)))
(defmacro cons-stream ( . args)
`(cons ,(car args) (delay ,(cadr args))))
(define head car)
(define (tail stream) (force (cdr stream)))
(define (filter-stream pred? stream)
(cond ((null? stream) stream)
((pred? (head stream))
(cons-stream (head stream)
(filter-stream pred? (tail stream))))
(else (filter-stream pred? (tail stream)))))
(define (reduce function base list)
(if (null? list)
base
(reduce function (function base (car list)) (cdr list))))
(define ten-e-stream (ten-consecutive-digits-stream (e-stream 10000)))
(define prime-stream (filter-stream prime? ten-e-stream))
(define sum-49-stream (filter-stream sum-49? ten-e-stream))
(display "primes: ")
(display (stream-to-list prime-stream 5))
(newline)
(display "sum 49s: ")
(display (stream-to-list sum-49-stream 5))
(newline)