;; lib/minikanren/tests/sudoku-4x4.sx — Sudoku 4×4 via CLP(FD).
;;
;; Grid in row-major order:
;;
;;   c0 c1 | c2 c3
;;   c4 c5 | c6 c7
;;   ------+------
;;   c8 c9 | cA cB
;;   cC cD | cE cF
;;
;; Each cell ∈ {1, 2, 3, 4}. 4 rows + 4 cols + 4 2x2 boxes are each a
;; distinct permutation.

(define digits-1-4 (list 1 2 3 4))

(define
  sudoku-4x4
  (fn
    (cells)
    (let
      ((c0 (nth cells 0))
        (c1 (nth cells 1))
        (c2 (nth cells 2))
        (c3 (nth cells 3))
        (c4 (nth cells 4))
        (c5 (nth cells 5))
        (c6 (nth cells 6))
        (c7 (nth cells 7))
        (c8 (nth cells 8))
        (c9 (nth cells 9))
        (cA (nth cells 10))
        (cB (nth cells 11))
        (cC (nth cells 12))
        (cD (nth cells 13))
        (cE (nth cells 14))
        (cF (nth cells 15)))
      (mk-conj
        (fd-in c0 digits-1-4)
        (fd-in c1 digits-1-4)
        (fd-in c2 digits-1-4)
        (fd-in c3 digits-1-4)
        (fd-in c4 digits-1-4)
        (fd-in c5 digits-1-4)
        (fd-in c6 digits-1-4)
        (fd-in c7 digits-1-4)
        (fd-in c8 digits-1-4)
        (fd-in c9 digits-1-4)
        (fd-in cA digits-1-4)
        (fd-in cB digits-1-4)
        (fd-in cC digits-1-4)
        (fd-in cD digits-1-4)
        (fd-in cE digits-1-4)
        (fd-in cF digits-1-4)
        (fd-distinct (list c0 c1 c2 c3))
        (fd-distinct (list c4 c5 c6 c7))
        (fd-distinct (list c8 c9 cA cB))
        (fd-distinct (list cC cD cE cF))
        (fd-distinct (list c0 c4 c8 cC))
        (fd-distinct (list c1 c5 c9 cD))
        (fd-distinct (list c2 c6 cA cE))
        (fd-distinct (list c3 c7 cB cF))
        (fd-distinct (list c0 c1 c4 c5))
        (fd-distinct (list c2 c3 c6 c7))
        (fd-distinct (list c8 c9 cC cD))
        (fd-distinct (list cA cB cE cF))
        (fd-label cells)))))

;; --- Tests ---

(mk-test
  "sudoku-4x4-empty-grid-count"
  (let
    ((sols (run* q (fresh (c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 cA cB cC cD cE cF) (== q (list c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 cA cB cC cD cE cF)) (sudoku-4x4 (list c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 cA cB cC cD cE cF))))))
    (len sols))
  288)

(mk-test
  "sudoku-4x4-impossible-clue-empty"
  (run*
    q
    (fresh
      (c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 cA cB cC cD cE cF)
      (== c0 1)
      (== c1 1)
      (== q (list c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 cA cB cC cD cE cF))
      (sudoku-4x4 (list c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 cA cB cC cD cE cF))))
  (list))

(mk-tests-run!)
