読者です 読者をやめる 読者になる 読者になる

計算機プログラムの構造と解釈 第二版 P210 問題3.81

sicp

問題を読んでもさっぱりだ。
いったん問題3.6に戻ってよく見直す。

自分が過去に作った答えなんてみつつ。
ここまでで、1時間くらいか。難しいな。


問題3.6だと

  • resetというメッセージを送って帰ってきた手続きに整数値を与える
  • 内部状態を使って持っている。

問題3.81(この問題)では

  • 内部状態は持たずに、要求をストリームの引数ととしてつかう
  • resetというメッセージはなくストリームから持ってきた値が整数だった場合、問題3.6のresetで整数値を与えたのと同じようにする。


代入は使うなとあるので、set!は使わない。
後は、問題3.6でつくった式をみつつ新しい手続きを作る。

#!/usr/local/bin/gosh
;; -*- coding: utf-8 -*-

(use ggc.debug.trace)
(use math.mt-random)
(load "./modules/stream.scm")

(define nil '())
(define disp display)
(define nl newline)

(define (rand-update x)
  (let ((a 12345829146347816)
        (b 65678375784084998)
        (m 81938662049))
    (modulo (+ (* a x) b) m)))


(define random-init 758687398445)


(define rand
  (let ((x random-init))
    (lambda ()
      (set! x (rand-update x))
      x)))


;;3.6で作ったrand
(define rand
  (let ((x random-init))
    (lambda (mes)
      (cond ((eq? mes 'generate)
             (set! x (rand-update x))
             x)
            ((eq? mes 'reset)
             (lambda (new-value)
               (set! x new-value)))
            (else (error "Unknown request -- RAND" mes))))))
           

;;3.81のrand
(define (rand stream randam-init)
  (define stream-rand
    (if (null? stream) the-empty-stream
      (let ((mes (stream-car stream)))
        (cons-stream
          (cond ((eq? mes 'generate) (rand-update randam-init))
                ((number? mes) (rand-update mes))
                (else (error "Unknown request -- RAND" mes)))
          (rand (stream-cdr stream) (stream-car stream-rand))))))
  stream-rand)


;;test用のstreamをつくる
(define test-stream
  (cons-stream 'generate
               (cons-stream 'generate
                            (cons-stream 'generate
                                         (cons-stream random-init
                                                      (cons-stream 'generate
                                                                   (cons-stream 'generate
                                                                                the-empty-stream)))))))


      
;;ストリームを見るための便利機能
(define (stream-viewer stream start count)

  (define (stream-initializer stream init-num)
    (if (= init-num 0) stream
      (stream-initializer (stream-cdr stream) (- init-num 1))))

  (define (show-stream stream count)
    (if (= count 0) (print "end")
      (begin
        (print (stream-car stream))
        (show-stream (stream-cdr stream) (- count 1)))))

  (begin
    (print "start")
    (show-stream (stream-initializer stream start) count)))



;; main
(define (main args)
  (stream-viewer (rand test-stream random-init) 0 6)
  0)


実行

start
24315662528
33476360939
41267492728
24315662528
33476360939
41267492728
end

ちゃんとresetの所(random-initの数)からresetされてます。