(sicp44)m3.50~3.59

dead-lockのところ

どうしても興味が持てないので飛ばしました><

stream

(define (prime? n)
  (cond ((<= n 0)
         (error n " is minuss"))
        ((<= n 3) #t)
        ((zero? (remainder n 2)) #f)
        (else
         (let ((sn (sqrt n)))
           (let loop ((n 3))
             (if (> n sn)
                 #t
                 (loop (+ n 2))))))))

;;0は素数なのかな?
;; (map (lambda (x) (cons x (prime? x))) (iota 20 1))

;; ;;面倒
;; (define (sum-primes a b)
;;   (let loop ((count a) (accum 0))
;;     (cond ((> count b) accum)
;;           ((prime? count)
;;            (iter (+ count 1) (+ count accum)))
;;           (else (iter (+ count 1) accum)))))
;; ;;遅い
;; (car (cdr (filter (prime?
;;                    (enumerate-interval 10000 100000)))))

;; (use util.stream)
;;streamが使える
;;(define the-empty-stream stream-null)
	;;挙動がsicpのものとは異なるらしい。

(define (memo-proc proc)
  (let ((already-run? #f) (result #f))
    (lambda ()
      (if (not already-run?)
          (begin
            (set! result (proc))
            (set! already-run? #t)
            result)
          result))))

(define-macro (delay x) `(memo-proc (lambda () ,x)))  ; memoizeあり ※stream-nomemo.scmではOFF
;(define-macro (delay x) `(lambda () ,x))             ; memoizeなし ※stream-nomemo.scmではON
(define (force x) (x))
(define-macro (stream-cons a b) `(cons ,a (delay ,b)))
(define (stream-car stream) (car stream))
(define (stream-cdr stream) (force (cdr stream)))
(define stream-null '())
(define stream-null? null?)


(define (stream-ref s n)
  (if (= n 0)
      (stream-car s)
      (stream-ref (stream-cdr s) (- n 1))))

(define (stream-map proc s)
  (if (stream-null? s)
      stream-null
      (stream-cons (proc (stream-car s))
                   (stream-map proc (stream-cdr s)))))

(define (stream-enumerate-interval beg end)
  (if (> beg end)
      stream-null
      (stream-cons beg
             (stream-enumerate-interval (+ beg 1) end))))

;; (define (stream-foreach proc . s)
;;   (if (stream-null? (car s))
;;       'done
;;       (begin (for-each proc (map stream-car s))
;;              (apply stream-foreach (cons proc (map stream-cdr s))))))

(define (stream-foreach proc s)
  (if (stream-null? s)
      'done
      (begin (proc (stream-car s))
             (stream-foreach proc (stream-cdr s)))))

                    
(define (display-stream s)
  (stream-foreach display-line s))

(define (display-line x)
  (newline) (display x))

;; (display-stream (stream-enumerate-interval 1 5)
;;                 (stream-enumerate-interval 10 15))

(define (stream-filter pred? s)
  (cond ((stream-null? s) stream-null)
        ((pred? (stream-car s))
          (stream-cons (stream-car s)
                       (stream-filter pred? (stream-cdr s))))
        (else
         (stream-filter pred? (stream-cdr s)))))

(stream-car
 (stream-cdr
  (stream-filter even?
                    (stream-enumerate-interval 10000 10000000))))



;;m3.50

(define (stream-map proc . argstreams)
  (if (stream-null? (stream-car argstreams))
      stream-null
      (stream-cons (apply proc (map stream-car argstreams))
                   ;;(apply stream-map (cons proc (map .....)))だと見にくい
                   (apply (cut stream-map proc <...>)
                          (map stream-cdr argstreams)))))

;;でも、cutにすると処理回数が2倍に増えてしまっているかも?
(define (stream->list s)
  (if (stream-null? s) 
      '()
      (cons (stream-car s) 
            (stream->list (stream-cdr s)))))

(stream->list (stream-map
               (lambda (x) (* x x))
               (stream-enumerate-interval 1 5)))
;; 10:user> => (1 4 9 16)
(stream->list (stream-map * (stream-enumerate-interval 1 5)
                            (stream-enumerate-interval 5 10)))
;; 11:user> => (5 12 21 32)


;;m3.51
(define sei stream-enumerate-interval)
(define (show x) (display-line x) x)
(define x (stream-map show (sei 0 10)))
(stream-ref x 5)
(stream-ref x 7)
;; 8:user> 
;; 1
;; 2
;; 3
;; 4
;; 5=> 5
;; 9:user> 
;; 6
;; 7=> 7

;;m3.52
(define sum 0)

(define (accum x)
  (set! sum (+ x sum)) sum)

(define seq (stream-map accum (sei 1 20)))
(define y (stream-filter even? seq))
;;sum=>6
;; 1, 3, 6(even) -> sum = 6
(define z (stream-filter (lambda (x) (= (remainder x 5) 0)) seq))
;; 6まで飛ばす。
;;sum=>10
;; 6, 10(10mod(5)==0) -> sum = 10
(stream->list z) ;;全部たどられる。
;; 35:user> => (10 15 45 55 105 120 190 210)
;;sum=>210

;;memo-procの最適化をしなかった場合は、yを定義した時点でsum=6
;;その後、zを定義する時にも、(1,2,3のところで)accumが呼ばれて違った値になる。



(define (integers-starting-from n)
  (stream-cons n (integers-starting-from (+ n 1))))

(define integers (integers-starting-from 1))

(define (divisubile? x y) (= (remainder x y) 0))

(define no-sevens
  (stream-filter (lambda (x) (not (divisubile? x 7)))
                 integers))
(stream-ref no-sevens 100)
;; 43:user> => 117

;;fibonachi
(define (fibgen a b)
  (stream-cons a (fibgen b (+ a b))))

(define fibs  (fibgen 0 1))
(stream-ref fibs 10)            
;; 48:user> => 55

;;Sieve of Eratosthenes
(define (sieve s)
  (stream-cons
   (stream-car s)
   (sieve (stream-filter (lambda (x)
                           (not (divisubile? x (stream-car s))))
                         (stream-cdr s)))))

(define primes (sieve (integers-starting-from 2)))
(map (cut stream-ref primes <>) (list 1 10 100))
;; 59:user> => (3 31 547)

(define ones (stream-cons 1 ones))
(define (add-streams s1 s2)  (stream-map + s1 s2))
(define integers (stream-cons 1 (add-streams ones integers)))

;; (map (cut stream-ref integers <>) (iota 10))
;; 65:user> => (1 2 3 4 5 6 7 8 9 10)
(define (f s)
  (map (cut stream-ref s <>) (iota 10)))


(define fibs
  (stream-cons 0
               (stream-cons 1 (add-streams (stream-cdr fibs)
                                           fibs))))
(f fibs)
;; 18:user> => (0 1 1 2 3 5 8 13 21 34)

(define (scale-stream s d)  (stream-map (cut * d <>) s))

(define double (stream-cons 1
                            (scale-stream double 2)))
(f double)
;; 19:user> => (1 2 4 8 16 32 64 128 256 512)

(define primes
  (stream-cons 2
               (stream-filter prime? (integers-starting-from 3))))
(f primes)
;; 21:user> => (2 3 5 7 9 11 13 15 17 19)

;;m3.53
(define s (stream-cons 1 (add-streams s s)))
;;2の冪乗。
(f s)
;; 22:user> => (1 2 4 8 16 32 64 128 256 512)

;; m3.54
(define (mul-streams s1 s2)  (stream-map * s1 s2))
(define factorials
  (stream-cons 1 (mul-streams integers factorials)))
(f factorials)
;; 23:user> => (1 1 2 6 24 120 720 5040 40320 362880)

;; m3.55
;; S->s0, s0+s1, s0+s1+s2
(define (partial-sums s)
  (stream-cons (stream-car s)
               (add-streams (partial-sums s) (stream-cdr s))))
(f (partial-sums integers))
;; 25:user> => (1 3 6 10 15 21 28 36 45 55)

;; m3.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)
                  (stream-cons s1car (merge (stream-cdr s1) s2)))
                 ((> s1car s2car)
                  (stream-cons s2car (merge s1 (stream-cdr s2))))
                 (else
                  (stream-cons s1car
                               (merge (stream-cdr s1)
                                      (stream-cdr s2)))))))))

(define S (stream-cons 1 (merge (merge (scale-stream S 2)
                                       (scale-stream S 3))
                                (scale-stream S 5))))
(f S)
;; 24:user> => (1 2 3 4 5 6 8 9 10 12)


;; m3.57
;;名前呼びだと毎回最初から呼ばれてしまう。
;; (stream-ref fibs (+ n 1))の計算回数を(f n+1)とかくと
;; (fi n+1) = (fi n) + (fi n-1) + 1

;; m3.58
(define (expand num den radix)
   (let ((nr (* num radix)))
     (stream-cons
     (quotient nr den)
     (expand (remainder nr den) den radix))))

(f (expand 1 7 10))
;; 27:user> => (1 4 2 8 5 7 1 4 2 8)
(f (expand 3 8 10))
;; 28:user> => (3 7 5 0 0 0 0 0 0 0)

;; m3.59
;; a.
(define (integrate-series s)
  (stream-map / s integers))

;; b.
(define exp-series
  (stream-cons 1 (integrate-series exp-series)))
;; 37:user> => (1 1 1/2 1/6 1/24 1/120 1/720 1/5040 1/40320 1/362880)
(define cosine-series
  (stream-cons 1 (stream-map (lambda (x) (* -1 x)) (integrate-series sine-series))))
(define sine-series
  (stream-cons 0 (stream-map * (integrate-series cosine-series))))
(f cosine-series)
;; 40:user> => (1 0 -1/2 0 1/24 0 -1/720 0 1/40320 0)
(f sine-series)
;; 41:user> => (0 1 0 -1/6 0 1/120 0 -1/5040 0 1/362880)