Created
March 30, 2012 17:40
-
-
Save gberenfield/2253264 to your computer and use it in GitHub Desktop.
week 3 - rover part 2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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! | |
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
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
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