Last active
January 11, 2017 12:05
-
-
Save davidporter-id-au/5a6e9f4b661da3aea1bd09d57ef439a9 to your computer and use it in GitHub Desktop.
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
(def direction-map ["R3", "R1", "R4", "L4", "R3", "R1", "R1", "L3", "L5", "L5", "L3", "R1", "R4", "L2", "L1", "R3", "L3", "R2", "R1", "R1", "L5", "L2", "L1", "R2", "L4", "R1", "L2", "L4", "R2", "R2", "L2", "L4", "L3", "R1", "R4", "R3", "L1", "R1", "L5", "R4", "L2", "R185", "L2", "R4", "R49", "L3", "L4", "R5", "R1", "R1", "L1", "L1", "R2", "L1", "L4", "R4", "R5", "R4", "L3", "L5", "R1", "R71", "L1", "R1", "R186", "L5", "L2", "R5", "R4", "R1", "L5", "L2", "R3", "R2", "R5", "R5", "R4", "R1", "R4", "R2", "L1", "R4", "L1", "L4", "L5", "L4", "R4", "R5", "R1", "L2", "L4", "L1", "L5", "L3", "L5", "R2", "L5", "R4", "L4", "R3", "R3", "R1", "R4", "L1", "L2", "R2", "L1", "R4", "R2", "R2", "R5", "R2", "R5", "L1", "R1", "L4", "R5", "R4", "R2", "R4", "L5", "R3", "R2", "R5", "R3", "L3", "L5", "L4", "L3", "L2", "L2", "R3", "R2", "L1", "L1", "L5", "R1", "L3", "R3", "R4", "R5", "L3", "L5", "R1", "L3", "L5", "L5", "L2", "R1", "L3", "L1", "L3", "R4", "L1", "R3", "L2", "L2", "R3", "R3", "R4", "R4", "R1", "L4", "R1", "L5"]) | |
;(def direction-map ["R8", "R4", "R4", "R8"]) | |
(def directions-list [:N :E :S :W]) | |
(def start-state {:d :N :l {:x 0 :y 0} :v []}) | |
(defn rotate [rel-direction facing-currently] | |
(let [ | |
dir-to-int (fn [d] (.indexOf directions-list d)) | |
curr-dir-facing-int (dir-to-int facing-currently) | |
int-to-dir (fn [i] (nth directions-list (Math/abs (mod i 4)))) | |
] | |
(cond | |
(= rel-direction "R") (int-to-dir (+ curr-dir-facing-int 1)) | |
(= rel-direction "L") (int-to-dir (- curr-dir-facing-int 1)) | |
:else (throw (Exception. (str "An invalid instruction was received: " rel-direction)))))) | |
(defn append-to-visit-log [state loc] | |
(assoc-in state [:v] (conj (:v state) loc))) | |
(defn abs-decrement-delta [delta] | |
"Send delta towards zero, or, use logic because I can't use simple mathematics" | |
(cond | |
(> delta 0) (dec delta) | |
(< delta 0) (inc delta) | |
:else 0)) | |
(defn inch-y [delta current-location state direction] | |
(let [ | |
inch-direction (if (< delta 0) -1 1) | |
updated-state (-> (append-to-visit-log state current-location) | |
(assoc :l current-location) | |
(assoc :d direction)) | |
next-location (assoc-in current-location [:y] (+ (:y current-location) inch-direction)) | |
] | |
(if (= 0 delta) | |
(assoc state :l current-location) | |
;else, keep inching recursively, adding to the map of entries visited | |
(inch-y (abs-decrement-delta delta) next-location updated-state direction)))) | |
(defn inch-x [delta current-location state direction] | |
(let [ | |
updated-state (-> (append-to-visit-log state current-location) | |
(assoc :l current-location) | |
(assoc :d direction)) | |
inch-direction (if (< delta 0) -1 1) | |
next-location (assoc-in current-location [:x] (+ (:x current-location) inch-direction)) | |
] | |
(if (= 0 delta) | |
(assoc state :l current-location) | |
(inch-x (abs-decrement-delta delta) next-location updated-state direction)))) | |
(defn move [direction distance state] | |
"Determines the new location and direction based on current state and direction" | |
(cond | |
(= direction :N) (inch-y distance (:l state) state direction) | |
(= direction :S) (inch-y (* -1 distance) (:l state) state direction) | |
(= direction :E) (inch-x distance (:l state) state direction) | |
(= direction :W) (inch-x (* -1 distance) (:l state) state direction) | |
:else (throw (Exception. (str "An invalid instruction was received: " direction))) | |
)) | |
(defn follow-directions [directions state] | |
(reduce (fn [curr-state r] | |
(let [direction-to-travel (rotate (subs r 0 1) (get-in curr-state [:d])) distance (. Integer parseInt (subs r 1))] | |
(move direction-to-travel distance curr-state))) | |
state | |
directions)) | |
(defn distance-between-two-points [a b] | |
"calculates the taxi-cab distance between two points" | |
(+ (Math/abs (- (get-in a [:y]) (get-in b [:y]))) | |
(Math/abs (- (get-in a [:x]) (get-in b [:x]))))) | |
(def first-double-visit (let [ | |
sequence-of-visits (:v (follow-directions direction-map start-state)) | |
frequencies (frequencies sequence-of-visits) | |
] | |
(first (filter (fn [el] (> (get-in frequencies [el]) 1 )) sequence-of-visits)))) | |
(distance-between-two-points first-double-visit (:l start-state)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment