Hi all,
I'm experimenting with clojure.core: very nice! This is a simple
planner for the Farmer Crosses River puzzle:
(def characters [:farmer :goat :wolf :cabbage])
;;; they all start on the left side of the river
(def _starting-state {:farmer :l, :goat :l :wolf :l :cabbage :l})
;;; they all must cross the river
(def _final-state {:farmer :r, :goat :r :wolf :r :cabbage :r})
(defn validstateo
"constraints for state s"
[s]
(fresh [farm goat wolf cabb]
(== s {:farmer farm, :goat goat, :wolf wolf, :cabbage cabb})
(conde
[(== farm goat)] ; farmer is with goat
or...
[(!= wolf goat) (!= cabb goat)]))) ; goat/wolf (or goat/
cabbage) not alone
(defn initialstateo [s]
(== s _starting-state))
(defn finalstateo [s]
(== s _final-state))
(defn doactiono [s a ns] ; state action nextstate
"action a change state s to state ns"
(fresh [farm goat wolf cabb]
(== s {:farmer farm, :goat goat, :wolf wolf, :cabbage cabb})
(validstateo ns) ; target state must be valid
(conde
;; farmer travels with goat
[(== a :bringgoat)
(== farm goat) ; they must be on the same side
(conde
;; flip side for them
[(== farm :l) (== ns {:farmer :r, :goat :r, :wolf
wolf, :cabbage cabb})]
[(== farm :r) (== ns {:farmer :l, :goat :l, :wolf
wolf, :cabbage cabb})])]
;; farmer travels with wolf
[(== a :bringwolf)
(== farm wolf)
(conde
[(== farm :l) (== ns {:farmer :r, :goat
goat, :wolf :r, :cabbage cabb})]
[(== farm :r) (== ns {:farmer :l, :goat
goat, :wolf :l, :cabbage cabb})])]
;; farmer travels with cabbage
[(== a :bringcabb)
(== farm cabb)
(conde
[(== farm :l) (== ns {:farmer :r, :goat goat, :wolf
wolf, :cabbage :r})]
[(== farm :r) (== ns {:farmer :l, :goat goat, :wolf
wolf, :cabbage :l})])]
;; farmer travels alone
[(== a :travalone)
(conde
[(== farm :l) (== ns {:farmer :r, :goat goat, :wolf
wolf, :cabbage cabb})]
[(== farm :r) (== ns {:farmer :l, :goat goat, :wolf
wolf, :cabbage cabb})])]
)))
(defne plano
"a plan is a sequence of (action, state) towards the final state"
[plan]
([[[?a ?s]]] (finalstateo ?s)) ; last state must be final
([[[?a ?s] . ?r]]
(fresh [a2 s2 r2]
(conso [a2 s2] r2 ?r)
(doactiono ?s a2 s2)
(plano ?r))))
(defn print-solution [sol]
(let [formatstring (clojure.string/join
""
(repeat (inc (count characters)) "%10s"))]
(print (format "%10s" "__ACTION__"))
(doseq [c characters] (print (format "%10s" c)))
(println)
(doseq [[a s] sol]
(let [row (cons a (map (fn [f] (f s))
characters))]
(println (apply (partial format formatstring) row))))))
This can be executed with:
(doseq [sol (set (run 1 [q]
(fresh [a s]
(firsto q [a s])
(initialstateo s)
(plano q))))]
(print-solution sol))
This is the output:
__ACTION__ :farmer :goat :wolf :cabbage
_.0 :l :l :l :l
:bringgoat :r :r :l :l
:travalone :l :r :l :l
:bringwolf :r :r :r :l
:bringgoat :l :l :r :l
:bringcabb :r :l :r :r
:travalone :l :l :r :r
:bringgoat :r :r :r :r
Due to lvar handling, I have problems in writing a more concise
version of doactiono: any idea?
Moreover, core.logic should be more informative, e.g. if I try to
execute:
user> (run* [q] (== q (firsto [1 2]))) ; wrong use of firsto and
wrong number of args passed to it
the only message printed is:
; Evaluation aborted.
In any case, thanks to core.logic authors!
Ciao
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en