;; lib/minikanren/tests/fd.sx — Phase 6 piece A: ino + all-distincto.

;; --- ino ---

(mk-test
  "ino-element-in-domain"
  (run* q (ino q (list 1 2 3)))
  (list 1 2 3))

(mk-test "ino-empty-domain" (run* q (ino q (list))) (list))

(mk-test
  "ino-singleton-domain"
  (run* q (ino q (list 42)))
  (list 42))

;; --- all-distincto ---

(mk-test
  "all-distincto-empty"
  (run* q (all-distincto (list)))
  (list (make-symbol "_.0")))

(mk-test
  "all-distincto-singleton"
  (run* q (all-distincto (list 1)))
  (list (make-symbol "_.0")))

(mk-test
  "all-distincto-distinct-three"
  (run* q (all-distincto (list 1 2 3)))
  (list (make-symbol "_.0")))

(mk-test
  "all-distincto-duplicate-fails"
  (run* q (all-distincto (list 1 2 1)))
  (list))

(mk-test
  "all-distincto-adjacent-duplicate-fails"
  (run* q (all-distincto (list 1 1 2)))
  (list))

;; --- ino + all-distincto: classic enumerate-all-permutations ---

(mk-test
  "fd-puzzle-three-distinct-from-domain"
  (let
    ((perms (run* q (fresh (a b c) (== q (list a b c)) (ino a (list 1 2 3)) (ino b (list 1 2 3)) (ino c (list 1 2 3)) (all-distincto (list a b c))))))
    (and
      (= (len perms) 6)
      (and
        (some (fn (p) (= p (list 1 2 3))) perms)
        (and
          (some
            (fn (p) (= p (list 1 3 2)))
            perms)
          (and
            (some
              (fn (p) (= p (list 2 1 3)))
              perms)
            (and
              (some
                (fn (p) (= p (list 2 3 1)))
                perms)
              (and
                (some
                  (fn (p) (= p (list 3 1 2)))
                  perms)
                (some
                  (fn (p) (= p (list 3 2 1)))
                  perms))))))))
  true)

(mk-tests-run!)
