Skip to content

Instantly share code, notes, and snippets.

@munro
Last active December 24, 2015 01:54
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 munro/36f82883eb89d38c4452 to your computer and use it in GitHub Desktop.
Save munro/36f82883eb89d38c4452 to your computer and use it in GitHub Desktop.
(:use '[clojure.core.logic :as m])
(defn concato "Logic equality of concatted vars equal to a list.
To illustrate how this works, here's an example of concat var solving without using this function.
(m/run* [a b c d]
(m/fresh [t1 t2]
(m/appendo a t1 [1 2 3 4])
(m/appendo b t2 t1)
(m/appendo c d t2)))"
[vars value]
(cond
(empty? vars) (m/emptyo value)
(= 1 (count vars)) (m/== (first vars) [value])
:else
(m/and*
(loop [acc []
var-list (conj (into [] (map vector (drop-last 2 vars) (repeatedly m/lvar))) [(last (drop-last vars)) (last vars)])
last-end value]
(if (empty? var-list)
acc
(let [[var-x var-sep] (first var-list)
var-rest (rest var-list)]
(recur (conj acc (m/appendo var-x var-sep last-end)) var-rest var-sep)))))))
(deftest concato-test
(is (= (m/run* [q]
(concato [] []))
['_0])
"concato no variables to an empty list should succeed")
(is (= (m/run* [q]
(concato [] [1 2 3]))
[])
"concato no variables to a non-empty list should fail")
(is (= (m/run* [a]
(concato [a] [1 2 3]))
[[[1 2 3]]])
"concato 1 variable should equal the list")
(is (= (m/run* [a b]
(concato [a b] [1 2 3]))
[[[] [1 2 3]]
[[1] [2 3]]
[[1 2] [3]]
[[1 2 3] []]]))
(is (= (m/run* [a b c]
(concato [a b c] [1 2 3 4]))
[[[] [] [1 2 3 4]]
[[] [1] [2 3 4]]
[[1] [] [2 3 4]]
[[] [1 2] [3 4]]
[[] [1 2 3] [4]]
[[1] [2] [3 4]]
[[] [1 2 3 4] []]
[[1 2] [] [3 4]]
[[1] [2 3] [4]]
[[1] [2 3 4] []]
[[1 2] [3] [4]]
[[1 2 3] [] [4]]
[[1 2] [3 4] []]
[[1 2 3] [4] []]
[[1 2 3 4] [] []]])))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment