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 clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to