Path: ...!2.eu.feeder.erje.net!feeder.erje.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: "B. Pym" Newsgroups: comp.lang.lisp,comp.lang.scheme Subject: Re: Non-determinism Date: Wed, 24 Jul 2024 04:41:59 -0000 (UTC) Organization: A noiseless patient Spider Lines: 154 Message-ID: References: MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Injection-Date: Wed, 24 Jul 2024 06:41:59 +0200 (CEST) Injection-Info: dont-email.me; posting-host="dc013996b5bb46648d47418209f67001"; logging-data="1699163"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18Hya/Rt1Tj4/o2APooeoDh" User-Agent: XanaNews/1.18.1.6 Cancel-Lock: sha1:pc4wnI7x3QTGREHJZZ3lX2XHKb0= Bytes: 5046 B. Pym wrote: > Problem 4.42 in SICP > > Five school girls took an exam. As they think thattheir > parents are too much interested in their score, they promise > that they write one correct and one wrong informations to > their parents. Followings are parts of their letters > concerning their result: > > Betty: Kitty was the second and I third. > Ethel: I won the top and Joan the second. > Joan: I was the third and poor Ethel the last. > Kitty: I was the second and Mary the fourth. > Mary: I was the fourth. Betty won the top. > > Guess the real order of the five school girls. Shorter: (define (xor a b) (if a (not b) b)) (define (either a m b n lst) (xor (= m (amb-index a lst)) (= n (amb-index b lst)))) (define (girls-exam) (amb-set-of (let* ((girls '(kitty betty ethel joan mary)) (answer (amb-permutation girls))) (amb-assert (either 'kitty 2 'betty 3 answer)) (amb-assert (either 'kitty 2 'mary 4 answer)) (amb-assert (either 'mary 4 'betty 1 answer)) (amb-assert (either 'ethel 1 'joan 2 answer)) ;; Next line not needed. ;; (amb-assert (either 'joan 3 'ethel 5 answer)) answer))) (girls-exam) ===> ((kitty joan betty mary ethel)) Supporting code: ;; Modified from the excellent code found here ;; http://www.shido.info/lisp/scheme_amb_e.html ;; and written by ;; SHIDO, Takafumi ;; [ SHIDO's comment ] ;; Notice that you cannot use the code shown in this chapter if ;; the searching path has loops. See SICP 4.3. for detailed ;; information on this matter. ;;; This function is re-assigned in `amb-choose' and `amb-fail' itself. (define amb-fail #f) ;;; function for nondeterminism (define (amb-choose . ls) (if (null? ls) (amb-fail) (let ((fail0 amb-fail)) (call/cc (lambda (cc) (set! amb-fail (lambda () (set! amb-fail fail0) (cc (apply amb-choose (cdr ls))))) (cc (car ls))))))) ;;; nondeterminism macro operator (define-syntax amb (syntax-rules () ((_) (amb-fail)) ((_ a) a) ((_ a b ...) (let ((fail0 amb-fail)) (call/cc (lambda (cc) (set! amb-fail (lambda () (set! amb-fail fail0) (cc (amb b ...)))) (cc a))))))) ;;; returning all possibilities (define-syntax amb-set-of (syntax-rules () ((_ s) (let ((acc '())) (amb (let ((v s)) (set! acc (cons v acc)) (amb-fail)) (reverse acc)))))) ;; (reverse! acc)))))) ;;; if not bool backtrack (define (amb-assert bool) (or bool (amb))) ;;; returns arbitrary number larger or equal to n (define (amb-integer-starting-from n) (amb n (amb-integer-starting-from (+ 1 n)))) ;;; returns arbitrary number between a and b (define (amb-number-between a b) (let loop ((i a)) (if (> i b) (amb) (amb i (loop (+ 1 i)))))) ;; (amb i (loop (1+ i)))))) ;;; write following at the end of file ;;; initial value for amb-fail (call/cc (lambda (cc) (set! amb-fail (lambda () (cc 'no-choice))))) (define (amb-all-different? . ls) (let loop ((obj (car ls)) (ls (cdr ls))) (or (null? ls) (and (not (member obj ls)) (loop (car ls) (cdr ls)))))) ;; [Written by me.] (define (amb-permutation lst) (let ((tmp (map (lambda(_) (apply amb-choose lst)) lst))) (amb-assert (apply amb-all-different? tmp)) tmp)) ;; First position is numbered 1. [Written by me.] (define (amb-index x xs) (let ((tail (member x xs))) (and tail (- (length xs) -1 (length tail))))) ;; Takes into consideration that y may appear ;; more than once. [Written by me.] (define (amb-before? x y lst) (let ((a (member x lst))) (and a (let ((b (member y lst))) (or (not b) (> (length a) (length b)))))))