;; lib/minikanren/queens.sx — N-queens via ino + all-distincto + project. ;; ;; Encoding: q = (c1 c2 ... cn) where ci is the column of the queen in ;; row i. Each ci ∈ {1..n}; all distinct (no two queens share a column); ;; no two queens on the same diagonal (|ci - cj| ≠ |i - j| for i ≠ j). ;; ;; The diagonal check uses `project` to escape into host arithmetic ;; once both column values are ground. (define safe-diag (fn (a b dist) (project (a b) (if (= (abs (- a b)) dist) fail succeed)))) (define safe-cell-vs-rest (fn (c c-row others next-row) (cond ((empty? others) succeed) (:else (mk-conj (safe-diag c (first others) (- next-row c-row)) (safe-cell-vs-rest c c-row (rest others) (+ next-row 1))))))) (define all-cells-safe (fn (cols start-row) (cond ((empty? cols) succeed) (:else (mk-conj (safe-cell-vs-rest (first cols) start-row (rest cols) (+ start-row 1)) (all-cells-safe (rest cols) (+ start-row 1))))))) (define range-1-to-n (fn (n) (cond ((= n 0) (list)) (:else (append (range-1-to-n (- n 1)) (list n)))))) (define ino-each (fn (cols dom) (cond ((empty? cols) succeed) (:else (mk-conj (ino (first cols) dom) (ino-each (rest cols) dom)))))) (define queens-cols (fn (cols n) (let ((dom (range-1-to-n n))) (mk-conj (ino-each cols dom) (all-distincto cols) (all-cells-safe cols 1)))))