Skip to content

Instantly share code, notes, and snippets.

@gberenfield
Created March 30, 2012 17:40
Show Gist options
  • Save gberenfield/2253264 to your computer and use it in GitHub Desktop.
Save gberenfield/2253264 to your computer and use it in GitHub Desktop.
week 3 - rover part 2
(ns codelesson.week3-1
(:require [clojure.string])
(:gen-class))
(defn merge-with-padding [x y]
" merge arrays x & y and padding the shorter of the two with nils "
(let [cx (count x) cy (count y)]
(if (not= cx cy)
(if (< cx cy)
(map #(vector %1 %2) (concat x (take (- cy cx) (repeat nil) )) y)
(map #(vector %1 %2) x (concat y (take (- cx cy) (repeat nil) ))))
(map #(vector %1 %2) x y))))
(defn char-to-i [c]
" cheezy character to int coverter "
(- (int c) 48))
(defn coord [thegrid x y]
(let [gridy (dec (count thegrid))]
((thegrid (- gridy y)) x)))
(defn get-rover-coords [rover-num]
(println "Enter rover" rover-num " initial coords")
(let [in (read-line)
v (filter #(not= \space %) (vec in))] ; [\1 \2 \N]
{:name (keyword (str rover-num)) :position [(char-to-i (first v)) (char-to-i (second v))] :facing (last v)}))
(defn get-grid-size []
(println "Enter the grid dimensions")
(let [in (read-line)]
[ (char-to-i (first in)) (char-to-i (last in)) ]))
(defn get-rover-mvmt [rover-num]
(println "Enter movement instructions for rover" rover-num)
(read-line))
(defn set-coord [thegrid rover contents]
"returns grid with rover at it's :position"
(let [gridy (dec (count thegrid)) x (first (:position rover)) y (last (:position rover))]
(assoc-in thegrid [(- gridy y) x] contents)))
;(assoc-in thegrid (:position rover) rover))
(defn create-grid [x y rover1 rover2]
(let [row (vec (repeat (inc y) {}))
grid (vec (repeat (inc x) row))
grid (set-coord grid rover1 rover1)
grid (set-coord grid rover2 rover2)]
grid))
(def turn-left {\E \N \N \W \W \S \S \E})
(def turn-right {\E \S \S \W \W \N \N \E})
(def turn {\L turn-left \R turn-right})
(defn forward [x y facing rovername]
"returns new {:position [x y] :facing facing} after moving forward 1-coordinate"
(condp = facing
\N {:position [x (inc y)] :facing facing :name rovername}
\S {:position [x (dec y)] :facing facing :name rovername}
\E {:position [(inc x) y] :facing facing :name rovername}
\W {:position [(dec x) y] :facing facing :name rovername}
nil))
(defn rover-moved [rover move]
" returns a new rover map after the move"
(let [x (first (:position rover)) y (last (:position rover)) facing (:facing rover) rovername (:name rover)]
(cond
(or (= move \L) (= move \R)) {:position [x y] :facing ((turn move) facing) :name rovername}
(= move \M) (forward x y facing rovername)
(nil? move) rover
:default (throw (do (println "Shouldn't hit this in rover-moved!"))))))
(defn not-in-bounds? [rover grid]
(let [x (first (:position rover)) y (last (:position rover))
size-x (count grid) size-y (count (get grid 0))]
(if (and (< x size-x) (< y size-y) (>= x 0) (>= y 0))
false
true)))
(defn check-moves [r1new r2new grid]
(cond
(not-in-bounds? r1new @grid) [false "Rover 1 out of bounds!"]
(not-in-bounds? r2new @grid) [false "Rover 2 out of bounds!"]
(= (:position r1new) (:position r2new)) [false "Crash!!!!!!"]
:default [true true]))
(defn update-grid [grid r1 r1new r2 r2new]
(dosync
(send grid set-coord r1 {})
(send grid set-coord r1new r1new)
(send grid set-coord r2 {})
(send grid set-coord r2new r2new)
[r1new r2new]))
(defn parse-move [state move grid]
" returns [{rover1map} {rover2map} [grid]]"
(let [r1move (first move)
r2move (last move)
r1 (first state)
r2 (second state)
r1new (rover-moved r1 r1move)
r2new (rover-moved r2 r2move)
validmove (check-moves r1new r2new grid)]
(if (first validmove)
(update-grid grid r1 r1new r2 r2new)
validmove)))
(defn showgrid [grid]
(await grid)
(doseq [row @grid]
(prn row)))
(defn spit-state [state grid]
(let [rover1 (first state) rover2 (second state)]
(println (first (:position rover1)) (last (:position rover1)) (:facing rover1))
(println (first (:position rover2)) (last (:position rover2)) (:facing rover2))
(showgrid grid)))
(defn spit-error [grid error]
(showgrid grid)
(println error))
(defn rove [grid-x grid-y rover1-initial-pos rover1-moves rover2-initial-pos rover2-moves]
(let [ grid (agent (create-grid grid-x grid-y rover1-initial-pos rover2-initial-pos))]
(loop [rover-state [rover1-initial-pos rover2-initial-pos ]
current-move (first (merge-with-padding rover1-moves rover2-moves))
moves (rest (merge-with-padding rover1-moves rover2-moves))]
(if (and (not-empty current-move) (first rover-state))
(recur (parse-move rover-state current-move grid) (first moves) (rest moves))
(if (false? (first rover-state))
(spit-error grid (last rover-state))
(spit-state rover-state grid))))))
(defn -main[] ; works with 'lein trampoline run'
(let [grid-dims (get-grid-size)
rover1-pos (get-rover-coords 1)
rover1-mvmt (get-rover-mvmt 1)
rover2-pos (get-rover-coords 2)
rover2-mvmt (get-rover-mvmt 2)]
(rove (first grid-dims) (last grid-dims) rover1-pos rover1-mvmt rover2-pos rover2-mvmt)))
(rove 5 5 {:name :rover1 :position [1 2] :facing \N} "LMLMLMLMM" {:name :rover2 :position [3 3] :facing \E} "MMRMMRMRRM")
(rove 3 3 {:name :rover1 :position [1 2] :facing \N} "LMLMLMLMM" {:name :rover2 :position [3 3] :facing \E} "MMRMMRMRRM") ; contrive out of bounds
(rove 3 3 {:name :rover1 :position [2 0] :facing \N} "MMMMMMM" {:name :rover2 :position [0 2] :facing \E} "MMMMRRRM") ; contrive a crash!
@gberenfield
Copy link
Author

Output for
(rove 5 5 {:name :rover1 :position [1 2] :facing \N} "LMLMLMLMM" {:name :rover2 :position [3 3] :facing \E} "MMRMMRMRRM")

1 3 N
5 1 E
[{} {} {} {} {} {}]
[{} {} {} {} {} {}]
[{} {:position [1 3], :facing \N, :name :rover1} {} {} {} {}]
[{} {} {} {} {} {}]
[{} {} {} {} {} {:position [5 1], :facing \E, :name :rover2}]
[{} {} {} {} {} {}]
nil

@gberenfield
Copy link
Author

Output for
(rove 3 3 {:name :rover1 :position [1 2] :facing \N} "LMLMLMLMM" {:name :rover2 :position [3 3] :facing \E} "MMRMMRMRRM") ; contrive out of bounds

[{} {} {} {:position [3 3], :name :rover2, :facing \E}]
[{} {:position [1 2], :name :rover1, :facing \N} {} {}]
[{} {} {} {}]
[{} {} {} {}]
Rover 2 out of bounds!
nil

@gberenfield
Copy link
Author

Output for
(rove 3 3 {:name :rover1 :position [2 0] :facing \N} "MMMMMMM" {:name :rover2 :position [0 2] :facing \E} "MMMMRRRM") ; contrive a crash!

[{} {} {} {}]
[{} {:position [1 2], :facing \E, :name :rover2} {} {}]
[{} {} {:position [2 1], :facing \N, :name :rover1} {}]
[{} {} {} {}]
Crash!!!!!!
nil

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment