Skip to content

Instantly share code, notes, and snippets.

@budu
Created April 17, 2012 02:24
Show Gist options
  • Save budu/2402996 to your computer and use it in GitHub Desktop.
Save budu/2402996 to your computer and use it in GitHub Desktop.
Logic puzzle: XKCD #287 solution in Clojure core.logic
(use 'clojure.core.logic)
(def rvar? (comp not lvar?))
(defmacro arithm [r x y op po]
`(fn [a#]
(let [r# (walk a# ~r)
x# (walk a# ~x)
y# (walk a# ~y)]
(cond
(and (lvar? r#) (rvar? x#) (rvar? y#))
(or (unify a# ~r (~op x# y#)) nil)
(and (rvar? r#) (lvar? x#) (rvar? y#))
(or (unify a# ~x (~po r# y#)) nil)
(and (rvar? r#) (rvar? x#) (lvar? y#))
(or (unify a# ~y (~po r# x#)) nil)
(and (rvar? r#) (rvar? x#) (rvar? y#)
(clojure.core/= r# (~op x# y#))) a#
:else nil))))
(defmacro plus [r x y]
`(arithm ~r ~x ~y + -))
(defmacro mul [r x y]
`(arithm ~r ~x ~y * /))
(defne mulseqo [xs ys zs]
([[] [] []])
([[x . xt] [y . yt] _]
(fresh [z zt]
(conso z zt zs)
(mul z x y)
(mulseqo xt yt zt))))
(defne reduceaddo [r coll]
([0 []])
([_ [x . tail]]
(fresh [z]
(plus r x z)
(reduceaddo z tail))))
(defn xkcd287 []
(run* [q]
(fresh [total prices counts amounts mf ff ss hw ms sp]
(== total 1505)
(== prices [215 275 335 355 420 580])
(== counts [mf ff ss hw ms sp])
(ino [mf ff ss hw ms sp] (range 8))
(mulseqo prices counts amounts)
(reduceaddo total amounts)
(== q [prices counts]))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment