Skip to content

Instantly share code, notes, and snippets.

@nodename
Created February 6, 2012 07:00
Show Gist options
  • Save nodename/1750339 to your computer and use it in GitHub Desktop.
Save nodename/1750339 to your computer and use it in GitHub Desktop.
Coding exercise #1: Mars Rovers
(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