Skip to content

Instantly share code, notes, and snippets.

@kayr
Created January 6, 2020 15:55
Show Gist options
  • Save kayr/942b317e8d4379b4b965d9edf3f90f0c to your computer and use it in GitHub Desktop.
Save kayr/942b317e8d4379b4b965d9edf3f90f0c to your computer and use it in GitHub Desktop.
Mars rover clojure
(ns mars-rover)
(def directions [:n :e :s :w])
(def opposites {:e :w
:w :e
:n :s
:s :n})
(defmulti move-step (fn [_ dir] dir))
(defmethod move-step :n [[x y] _] [x (+ y 1)])
(defmethod move-step :s [[x y] _] [x (- y 1)])
(defmethod move-step :e [[x y] _] [(+ x 1) y])
(defmethod move-step :w [[x y] _] [(- x 1) y])
(defn forward [point dir] (move-step point dir))
(defn backward [point dir] (->> (dir opposites) (move-step point)))
(defn get-next [item coll]
(->>
(concat coll [(first coll)])
(drop-while #(not= %1 item))
(second)))
(defn get-prev [item coll] (->> (reverse coll) (get-next item)))
(defn turn-right [dir] (get-next dir directions))
(defn turn-left [dir] (get-prev dir directions))
(defn collided [[x1 y1] [x2 y2]] (and (= x1 x2) (= y1 y2)))
(defmulti rcv-cmd (fn [_ cmd] (keyword (str cmd))))
(defmethod rcv-cmd :l [{rover :rover} _] (update rover :dir turn-left))
(defmethod rcv-cmd :r [{rover :rover} _] (update rover :dir turn-right))
(defmethod rcv-cmd :f [{{point :point dir :dir :as rover} :rover} _] (assoc rover :point (forward point dir)))
(defmethod rcv-cmd :b [{{point :point dir :dir :as rover} :rover} _] (assoc rover :point (backward point dir)))
(defn throw-if-colliding [point obstacles]
(run! #(if (collided %1 point)
(throw (RuntimeException. (str "Found collusion between at " point))))
obstacles))
(defn process-cmd [planet cmd]
(let [rover (rcv-cmd planet cmd)]
(throw-if-colliding (:point rover) (:obstacles planet))
(assoc planet :rover rover)))
(defn recv-cmds [rover obstacles commands]
(reduce process-cmd {:rover rover :obstacles obstacles} commands))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment