(require (planet "priority-queue.scm" ("soegaard" "galore.plt")))
(define n 6)
(define m 4)
(define width (+ n 4))
(define height (+ m 4))
(define (on-board? x)
(and (<= 2 (modulo x width) (+ n 1))
(<= 2 (quotient x width) (+ m 1))))
(define (neighbours x)
(define (u x) (- x width)) (define (d x) (+ x width)) (define (l x) (- x 1)) (define (r x) (+ x 1))
(filter on-board?
(list (u (u (r x))) (u (u (l x)))
(l (l (u x))) (l (l (d x)))
(d (d (l x))) (d (d (r x)))
(r (r (u x))) (r (r (d x))))))
(define (insert-all l pri pq)
(foldl (lambda (x pq) (insert x pri pq))
pq
l))
(define (find-tour start)
(define (search pq)
(if (empty? pq)
'no-solution
(let* ([tour (find-min pq)]
[pri (find-min-priority pq)]
[pq (delete-min pq)]
[extend-tour (lambda (x)
(cons x tour))]
[new? (lambda (x)
(not (member x tour)))])
(if (= pri (* m n))
(reverse tour)
(search (insert-all (map extend-tour
(filter new? (neighbours (first tour))))
(add1 pri)
pq))))))
(search (insert (list start) 1
(empty (lambda (n1 n2) (- (number-compare n1 n2)))))))
(define upper-left-corner (+ (* 2 width) 2))
(define (index x l)
(let loop ([i 0]
[l l])
(cond
[(null? l) #f]
[(= (first l) x) i]
[else (loop (add1 i) (rest l))])))
(define (interval m n)
(if (> m n)
'()
(cons m (interval (add1 m) n))))
(define (display-tour tour)
(define (display2 n)
(if (number? n)
(if (<= 0 n 9)
(begin
(display " ") (display n))
(display n))
(display n))
(display " "))
(if (not (list? tour))
(display "No solution")
(let loop ([x upper-left-corner])
(if (<= x (sub1 (* width (- height 2))))
(begin
(if (on-board? x)
(display2 (index x tour)))
(if (= (modulo x width) (sub1 width))
(newline))
(loop (add1 x)))
(void)))))
(display "Please wait...\n")
(time (display-tour (find-tour upper-left-corner)))