SICP 読み (230) 4.3.3 amb 評価器の実装

練習問題ヤる事にしたので追記でなく新たにエントリを。scheme って乱数は自分で手続き作らんといけんの??と言いつつ gauche と乱数で google 先生にお伺いを立ててみた所、math.mt-random というソレを発見。

gosh> (use math.mt-random)
#<undef>
gosh> (define m (make <mersenne-twister> :seed (sys-time)))
m
gosh> (mt-random-integer m 10)
8
gosh> (mt-random-integer m 10)
4
gosh> (mt-random-integer m 10)
9
gosh> 

こんなカンジで使えば良いみたいです。これを踏まえて問題 4.50 に別途トライ予定。

問題 4.50

完全モチ切れ。現実トウヒ全力投球状態に突入 (ってこんなコト書いていいんかいな)。とりあえず、上記の乱数な手続きと以下のソレがあれば実装可能と見た。

(define (list-ref items n)
  (if (= n 0)
      (car items)
      (list-ref (cdr items) (- n 1))))
(define (remainder items n)
  (if (= n 0)
      (cdr items)
      (cons (car items) (remainder (cdr items) (- n 1)))))

ざっくりベースで以下のような感じ?? (m は大域変数にしといて良いかなぁ)

(define (analyze-ramb exp)
  (let ((cprocs (map analyze (amb-choices exp))))
    (lambda (env succeed fail)
      (define (try-next choices)
	(let ((n (mt-random-integer m (length choices))))
	  (if (null? choices)
	      (fail)
	      ((list-ref choices n) 
	       env
	       succeed
	       (lambda () (try-next (remainder choices n)))))))
      (try-next cprocs))))

ちょっと m の取り扱いが微妙。