Created
February 6, 2012 07:00
-
-
Save nodename/1750339 to your computer and use it in GitHub Desktop.
Coding exercise #1: Mars Rovers
This file contains 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 rovers | |
(:use [clojure.string :only [split-lines]])) | |
(def *test-input* | |
"5 5 | |
1 2 N | |
LMLMLMLMM | |
3 3 E | |
MMRMMRMRRM") | |
(def headings '(:N :E :S :W)) | |
(def right (zipmap headings '(:E :S :W :N))) | |
(def left (zipmap headings '(:W :N :E :S))) | |
(def delta-x (zipmap headings '(0 1 0 -1))) | |
(def delta-y (zipmap headings '(1 0 -1 0))) | |
(defrecord Position [x y heading]) | |
(defprotocol PositionOps | |
(L [p]) | |
(R [p]) | |
(M [p]) | |
(show [p])) | |
(extend-type Position | |
PositionOps | |
(L [position] | |
(Position. (:x position) (:y position) (left (:heading position)))) | |
(R [position] | |
(Position. (:x position) (:y position) (right (:heading position)))) | |
(M [position] | |
(let [heading (:heading position) | |
dx (delta-x heading) | |
dy (delta-y heading)] | |
(Position. (+ dx (:x position)) (+ dy (:y position)) heading))) | |
(show [position] | |
(println (:x position) (:y position) (second (str (:heading position)))))) | |
;; There must be a way to avoid having to do these: | |
(def command-by-name {"L" L "R" R "M" M}) | |
(def heading-by-name {"N" :N "E" :E "S" :S "W" :S}) | |
(defn parse-position | |
[position-string] | |
(let [fields (vec (map read-string (re-seq #"[\w]" position-string)))] | |
(Position. (fields 0) (fields 1) (heading-by-name (str (fields 2)))))) | |
(defn parse-commands | |
[commands-string] | |
(vec commands-string)) | |
(defn run-commands | |
[command-names initial-position] | |
(loop [command-names command-names | |
position initial-position] | |
(cond (= 0 (.size command-names)) position | |
:else (let [command-name (command-names 0) | |
command (command-by-name (str command-name)) | |
newposition (command position)] | |
(recur (vec (rest command-names)) newposition))))) | |
(defn parse-rovers | |
[lines] | |
(loop [line 0] | |
(cond | |
(>= line (.size lines)) nil | |
:else (let [position-line (lines line) | |
commands-line (lines (inc line)) | |
initial-position (parse-position position-line) | |
commands (parse-commands commands-line)] | |
(show (run-commands commands initial-position)) | |
(recur (+ 2 line)))))) | |
(defn parse | |
[] | |
(let [lines (vec (split-lines *test-input*)) | |
maxcoords (vec (map read-string (re-seq #"[\d.]+" (lines 0)))) | |
max-x (maxcoords 0) | |
max-y (maxcoords 1)] | |
(parse-rovers (vec (rest lines))))) | |
(parse) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment