(declaim (optimize (speed 3) (safety 0) (debug 0))
(inline distance))
(defun distance (pos1 pos2)
(+ (expt (- (the unsigned-byte (car pos1)) (the unsigned-byte (car pos2))) 2)
(expt (- (the unsigned-byte (cdr pos1)) (the unsigned-byte (cdr pos2))) 2)))
(defun print-as-board (size poss)
(loop
for x below size
do (loop
for y below size
do (format t "~a"
(if (find (cons x y) poss :test #'equalp)
"o"
"+")))
(format t "~%")))
;; 遅いバージョン
(defun solve (size num)
(labels
((rec (i poss distances)
(when (zerop i)
(print-as-board size poss)
(return-from solve))
(loop
for x below size
do (loop
for y below size
for pos = (cons x y)
for ds = (mapcar (lambda (pos1) (distance pos pos1)) poss)
when (= (length poss)
(length (remove-duplicates ds)))
unless (find pos poss :test #'equalp)
unless (intersection distances ds)
do (rec (1- i) (cons pos poss) (append ds distances))))))
(rec num () ())))
(defun solve2 (size num)
(declare (unsigned-byte size num))
(let ((pos-array (make-array num :fill-pointer 0))
(dist-array (make-array (the unsigned-byte (/ (* num (1- num)) 2))
:element-type 'unsigned-byte
:initial-element 0)))
(labels
((rec (i di)
(when (zerop i)
(print-as-board size pos-array) (terpri)
(return-from solve2))
(loop
for x fixnum below size
do (loop
for y fixnum below size
for pos = (cons x y)
unless (find pos pos-array :test #'equalp)
unless (loop
for p across pos-array
for i from di
for d = (the unsigned-byte (distance pos p))
when (find d dist-array :end i)
return t
do (setf (aref dist-array i) d))
do (vector-push pos pos-array)
(rec (the unsigned-byte (1- i)) (+ di (length pos-array) -1))
(vector-pop pos-array)))))
(rec num 0))))
(solve2 5 5)
(solve2 6 6)