; a number puzzle
(define (split n xs)
(let loop ((n n) (xs xs) (zs '()))
(if (or (zero? n) (null? xs))
(values (reverse zs) xs)
(loop (- n 1) (cdr xs) (cons (car xs) zs)))))
(define (filter pred? xs)
(let loop ((xs xs) (ys '()))
(cond ((null? xs) (reverse ys))
((pred? (car xs))
(loop (cdr xs) (cons (car xs) ys)))
(else (loop (cdr xs) ys)))))
(define (digits n . args)
(let ((b (if (null? args) 10 (car args))))
(let loop ((n n) (d '()))
(if (zero? n) d
(loop (quotient n b)
(cons (modulo n b) d))))))
(define (undigits ds . args)
(let ((b (if (null? args) 10 (car args))))
(let loop ((ds ds) (n 0))
(if (null? ds) n
(loop (cdr ds) (+ (* n b) (car ds)))))))
(define (but-last xs) (reverse (cdr (reverse xs))))
(define (permutations xs)
(define (rev xs n ys)
(if (zero? n) ys
(rev (cdr xs) (- n 1) (cons (car xs) ys))))
(let ((xs xs) (perms (list xs)))
(define (perm n)
(if (> n 1)
(do ((j (- n 1) (- j 1)))
((zero? j) (perm (- n 1)))
(perm (- n 1))
(set! xs (rev xs n (list-tail xs n)))
(set! perms (cons xs perms)))))
(perm (length xs))
perms))
(define (check? digits)
(let loop ((digits digits) (n (length digits)))
(if (= n 1) #t
(if (not (zero? (modulo (undigits digits) n))) #f
(loop (but-last digits) (- n 1))))))
(define (puzzle)
(define (insert5 ds)
(call-with-values
(lambda () (split 4 ds))
(lambda (f b) (append f (list 5) b))))
(filter check?
(map insert5
(permutations
'(1 2 3 4 6 7 8 9)))))
(display (puzzle))