Skip to content

Instantly share code, notes, and snippets.

@hypirion
Forked from rf/test.clj
Created August 9, 2012 11:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hypirion/3303586 to your computer and use it in GitHub Desktop.
Save hypirion/3303586 to your computer and use it in GitHub Desktop.
(defn lookup
"Lookup a variable in the model. Respects inversion of the variable if it is
specified with a - symbol. Returns nil if the variable is unset."
[[first-char :as var] model]
(if (= first-char \-) ; If the first character is '-'
(if-let [[_ val] (find model (subs var 1))] ; test for existence
(not val) ; invert value if exists
nil) ; otherwise return nil
(get model v)))
(def foobar {"A" false, "B" true})
(println "should return false:" (lookup "A" foobar))
(println "should return false:" (lookup "-B" foobar))
(println "should return true:" (lookup "B" foobar))
(println "should return nil:" (lookup "-C" foobar))
(defn satisfiable?
"Checks to see if a given clause is satisfiable given a model."
[clause, model]
;; Test all clauses
(let [lookups (map #(lookup % model) clause)]
(cond (every? false? lookups) false
(some true? lookups) true
:otherwise nil)))
(def barbaz '("A" "-B"))
(def buzfuz '("-A" "-B"))
(def sprangadang '("A" "-B" "C"))
(println "should return false:" (satisfiable? barbaz foobar))
(println "should return true:" (satisfiable? buzfuz foobar))
(println "should return nil:" (satisfiable? sprangadang foobar))
(defn solve
"Solves some set of clauses recursively, given some model and some list of
variables present in the clauses."
[variables, clauses, model]
(let [satisfied-result (map #(satisfiable? % model) clauses)]
;; If every clause is satisfiable, the set of clauses is satisfied by the
;; current model, so we should return it.
(cond (every? true? satisfied-result) model
;; If some clause can't be satisfied, the set is not satisfiable given
;; this model.
(some false? satisfied-result) false
:otherwise ;; choose the first variable that is not yet defined
(let [choice (first (filter #(nil? (lookup % model)) variables))]
(if (nil? choice) false
;; And try setting it to true; if that doesn't work, try false.
(or
(solve variables clauses (assoc model choice true))
(solve variables clauses (assoc model choice false))))))))
(def rock '(("A" "-B") ("-A" "-B")))
(def paper '(("A" "-B") ("-A" "-B") ("A" "B" "C")))
(def scissors '(("-A" "B") ("-B") ("A")))
(println "should return a model:" (solve '("A" "B") rock {}))
(println "should return a model:" (solve '("A" "B" "C") paper {}))
(println "should return false:" (solve '("A" "B") scissors {}))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment