SICPを読む(94) 問題 3.6 - 乱数発生器改

嗚呼、Schemeすることは難しい事じゃない。ただ脳に身を任せ・・・(謎

問題 3.6

乱数発生器を改造して、resetを付ける問題。

generateは要らないと思うので、無くした。

(define random-init 12345)

(define (rand-update x)
  (modulo (+ (* 214013 x) 253011) 32767))

(define rand
  (let ((x random-init))
       (lambda m
         (set! x (if (and (not (null? m))
                          (eq? (car m) 'reset))
                     (if (null? (cdr m))
                         random-init
                         (cadr m))
                     (rand-update x)))
         x)))

テスト。

(rand)             ; 10917
(rand)             ; 18162
(rand 'reset)      ; 12345
(rand)             ; 10917
(rand)             ; 18162
(rand 'reset 9876) ; 9876
(rand)             ; 13462

こっちのほうが使いやすいと思う。

((rand 'reset) 10)

としたい場合は、(lambda (a) (set! x ...を返せばいい。


コードが見難いので、パターンマッチを使ってスッキリさせてみる。

(require (lib "match.ss"))

(define rand
  (let ((x random-init))
       (lambda m
         (set! x (match m
                        (() (rand-update x))
                        ((reset) random-init)
                        (`(reset ,a) a)
                        (_ 'error)))
         x)))

引数がいっぱいあった時はかなり有効そうだ。