Skip to content

Instantly share code, notes, and snippets.

@martintrojer
Created July 11, 2012 06:43
Show Gist options
  • Save martintrojer/3088470 to your computer and use it in GitHub Desktop.
Save martintrojer/3088470 to your computer and use it in GitHub Desktop.
queens blog, part 2
(defne nqueenso [l n]
([() _]) ;; queen list empty, s#
([[[x y] . t] _] ;; match/destruct head.tail, ignore n
(nqueenso t n)
(membero x (range n))
(safeo [x y] t)))
(defmacro queens-run
"Search for all N queens solutions"
[n]
(let [xnames (->> (range n) (map (fn [_] (gensym "x"))) (into []))
gen-safeos (fn []
(->> (range (dec n))
(map (fn [x] [x (range (inc x) n)]))
(map (fn [[s ts]]
(map (fn [t] `(safeo [~(nth xnames s) ~s]
[~(nth xnames t) ~t])) ts)))
(apply concat)))
]
`(run* [r#]
(fresh [~@(map #(nth xnames %) (range n))]
~@(map (fn [x] (list 'membero (xnames x) (into [] (range n)))) (range n))
~@(gen-safeos)
(== r# [~@(map (fn [x] [(nth xnames x) x])
(range n))])))))
(defne safeo
"Is the queen q safe from all queens in list others"
[q others]
([_ ()]) ;; others empty, s#
([[x1 y1] [[x2 y2] . t]] ;; destruct q and head.tail of others
(!= x1 x2)
(!= y1 y2)
(project [x1 x2 y1 y2]
(!= (- x2 x1) (- y2 y1))
(!= (- x1 y2) (- x2 y1)))
(safeo [x1 y1] t)))
(defn safeo [[x1 y1] [x2 y2]]
(all
(!= x1 x2)
(!= y1 y2)
(project [x1 x2 y1 y2]
(!= (- x2 x1) (- y2 y1))
(!= (- x1 y2) (- x2 y1)))))
@swannodette
Copy link

You don't need a macro to generalize nqueens to N. You can create logic vars on the fly.

@martintrojer
Copy link
Author

Indeed! I'm writing the blog post right now, these gists are used to build up to the grand finale! :)

@swannodette
Copy link

(declare noattacko)

(defne nqueenso [l n]
  ([() _])
  ([[[x y] . others] _]
     (nqueenso others n)
     (membero y (range 1 (inc n)))
     (noattacko [x y] others)))

(defne noattacko [q others]
  ([_ ()])
  ([[x y] [[x1 y1] . r]]
     (!= y y1)
     (project [y y1 x x1]
       (!= (- y1 y) (- x1 x))
       (!= (- y1 y) (- x x1)))
     (noattacko [x y] r)))

(defn solve-nqueens [n]
  (run* [q]
    (== q (map vector (range 1 (inc n)) (repeatedly lvar)))
    (nqueenso q n)))

@swannodette
Copy link

Oh haha, cool pasted before I saw your reply :)

@martintrojer
Copy link
Author

Thanks for all the help btw, you're a star. I've gotta bring you a box of chocolates if I manage to get to the next conj :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment