SICP 4.3.3 Ex. 4.53

  • 投稿日:
  • カテゴリ:

Ex. 4.53

結構準備がたいへん。

amb評価器も少し変更
(define primitive-procedures
  (list (list 'car car)
        ...
	(list 'remainder remainder) ;; prime?で使うので
        ...

amb評価器に事前に喰わせておくソース

;;; Amb-Eval input:
;;p.246
(define (require p)
  (if (not p) (amb)))
;;p.245
(define (an-element-of items)
  (require (not (null? items)))
  (amb (car items) (an-element-of (cdr items))))
;; p.28
(define (divides? a b)
  (= (remainder b a) 0))
;;p.15
(define (square x) (* x x))
;;p.28
(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)))))
;;p.28
(define (smallest-divisor n)
  (find-divisor n 2))
;;p.28
(define (prime? n)
  (= n (smallest-divisor n)))
;;p.245
(define (prime-sum-pair list1 list2)
  (let ((a (an-element-of list1))
	(b (an-element-of list2)))
    (require (prime? (+ a b)))
    (list a b)))

これで準備完了。

;;; Amb-Eval input:
;;p260 Ex.4.53
(let ((pairs '()))
      (if-fail (let ((p (prime-sum-pair '(1 3 5 8) '(20 35 110))))
		 (permanent-set! pairs (cons p pairs))
		 (amb))
	       pairs))

;;; Starting a new problem 
;;; Amb-Eval value:
((8 35) (3 110) (3 20))

いちいち try-again しなくても、ambで探索し発見したアイテムを全部まとめて入手できる。

ambの発見物でリストを作るのは permanent-set! の役目。if-fail がないと作ったリストを取り出せない。