Skip to content

Instantly share code, notes, and snippets.

@budu
Created April 12, 2012 05:03
Show Gist options
  • Save budu/2364695 to your computer and use it in GitHub Desktop.
Save budu/2364695 to your computer and use it in GitHub Desktop.
Logic puzzle: send more money solution in Clojure core.logic, translated from cKanren paper. Takes forever to run!
(use 'clojure.core.logic
'clojure.core.logic.arithmetic)
(defne diffo
[l]
([[]])
([[x]])
([[x y . tail]]
(fresh [l0 l1]
(!= x y)
(conso x tail l0)
(conso y tail l1)
(diffo l0)
(diffo l1))))
(defne ino
[l in]
([[] _])
([[x . tail] _]
(ino tail in)
(membero x in)))
(defmacro +fd [r & addends]
`(fn [a#]
(let [r# (walk a# ~r)
addends# (map (partial walk a#) [~@addends])]
(if (clojure.core/= (apply + addends#) r#)
a#
nil))))
(defn add-digits
[x y z cin cout]
(fresh [psum sum]
(membero psum (range 19))
(membero sum (range 20))
(+fd psum x y)
(+fd sum psum cin)
(conde
[(< 9 sum) (== cout 1) (+fd sum z 10)]
[(<= sum 9) (== cout 0) (== z sum)])))
(defn send-more-money []
(run* [q]
(fresh [s e n d m o r y c0 c1 c2]
(ino [e n d o r y] (range 10))
(ino [s m] (range 1 10))
(ino [c0 c1 c2] (range 2))
(== q [s e n d m o r y])
(diffo q)
(add-digits s m o c2 m)
(add-digits e o n c1 c2)
(add-digits n r e c0 c1)
(add-digits d e y 0 c0))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment