(load "mk.scm")
(load "mkextraforms.scm")
(load "mkprelude.scm")
A Sequence Program
Arrange three 1s, three 2s, ..., three 9s in sequence so that for all
i in [1, 9] there are exactly i numbers between successive occurrences
of i. An example of such a sequence is 1, 9, 1, 2, 1, 8, 2, 4, 6, 2,
7, 9, 4, 5, 8, 6, 3, 4, 7, 5, 3, 9, 6, 8, 3, 5, 7.
The problem is taken from
K.R. Apt, "The Logic Programming Paradigm and Prolog".
(Chapter 15 in Concepts in Programming Languages , J. Mitchell,
Cambridge University Press (2002).
available online at http://homepages.cwi.nl/~apt/ps/lp00.ps
|#
(define (make-sequence n out)
(if (= n 0)
(== '() out)
(fresh (x res)
(make-sequence (- n 1) res)
(conso x res out))))
(run* (out) (make-sequence 10 out))
|#
(define (list-refo lst index out)
(if (= index 0)
(caro lst out)
(fresh (d)
(cdro lst d)
(list-refo d (- index 1) out))))
(run* (q) (list-refo '(a b c) 2 q))
(run* (q) (list-refo '(a b c) 3 q))
|#
(define (is-starting-here? a seq next times)
(let loop ((index 0) (times times))
(if (= times 0)
succeed
(all
(list-refo seq index a)
(loop (+ index next) (- times 1))))))
(run* (q) (is-starting-here? 'a '(a b c a b c) 3 2))
(run* (q) (is-starting-here? 'a '(a b c a b c) 3 3))
(run* (q) (is-starting-here? 'a '(x a b c a b c) 3 2))
|#
(define (is-anywhere? a seq next times)
(let loop ((seq seq))
(condi ((nullo seq) fail)
((is-starting-here? a seq next times) succeed)
(else (fresh (d)
(cdro seq d)
(loop d))))))
(run* (q) (is-anywhere? 'a '(a b c a b c) 3 2))
(run* (q) (is-anywhere? 'a '(a b c a b c) 3 3))
(run* (q) (is-anywhere? 'a '(x a b c a b c a b c) 3 2))
|#
(define (number-sublist? n times seq)
(is-anywhere? n seq (+ n 1) times))
(run* (q) (number-sublist? 1 3 '(1 x 1 x 1)))
(run* (q) (number-sublist? 1 4 '(1 x 1 x 1)))
(run* (q) (number-sublist? 2 3 '(2 x y 2 a b 2)))
|#
(define (all-numbers-sublist? from to times seq)
(if (= from to)
succeed
(all
(number-sublist? from times seq)
(all-numbers-sublist? (+ from 1) to times seq))))
(run* (q) (all-numbers-sublist? 1 3 2 '(1 2 1 x 2)))
(run* (q) (all-numbers-sublist? 1 4 2 '(1 2 1 3 2)))
|#
(define (sequence-program from to times out)
(all
(make-sequence (* times (- to from)) out)
(all-numbers-sublist? from to times out)))
(run 1 (out) (sequence-program 1 10 3 out))
(run* (out) (sequence-program 1 4 2 out))
|#
(define (canonical-sequence-program out)
(sequence-program 1 10 3 out))
(run 1 (out) (canonical-sequence-program out))
(run* (out) (canonical-sequence-program out))
|#
(define (number-sublist? n times seq)
(fresh (sub)
(generate-number-list n times sub)
(sublist? sub seq)))
|#
(define (sublist? xs ys)
(fresh (zs a b)
(appendo a zs ys)
(appendo xs b zs)))
(run* (q) (sublist? '(b) '(a b c)))
(run* (q) (sublist? '(b d) '(a b c)))
|#
(define (generate-number-list number times out)
(let ((interval (+ number 1)))
(let loop ((index 0) (times times) (out out))
(if (= times 0)
(== '() out)
(fresh (res x)
(if (= index 0)
(== x number)
succeed)
(loop (remainder (+ index 1) interval)
(- times (if (= index 0) 1 0))
res)
(conso x res out))))))
(run* (out) (generate-number-list 1 3 out))
(run* (out) (generate-number-list 4 3 out))
|#