-
Notifications
You must be signed in to change notification settings - Fork 0
/
twelve.clj
87 lines (71 loc) · 2.9 KB
/
twelve.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
(ns twelve
(:require [clojure.string :as str]))
(defn read-directions []
(->> (slurp "resources/twelve.txt")
(str/split-lines)
(map (comp rest first (partial re-seq #"([NSEWLRF])(\d+)")))
(map (fn [[action amount]] [action (Integer/parseInt amount)]))))
(def left-turns {"E" "N"
"N" "W"
"W" "S"
"S" "E"})
(def right-turns {"E" "S"
"S" "W"
"W" "N"
"N" "E"})
(defn turn [state mapping degrees]
(let [turns (mod (/ degrees 90) 4)]
(last (take (inc turns) (iterate #(update % :direction mapping) state)))))
(defn step-ship [state [action amount]]
(case action
"N" (update state :y + amount)
"S" (update state :y - amount)
"E" (update state :x + amount)
"W" (update state :x - amount)
"L" (turn state left-turns amount)
"R" (turn state right-turns amount)
"F" (step-ship state [(:direction state) amount])))
(defn rotate-right [[[n e]
[w s]]]
[[w n]
[s e]])
(defn rotate-left [[[n e]
[w s]]]
[[e s]
[n w]])
(defn north [[[n _] _]] n)
(defn south [[_ [_ s]]] s)
(defn east [[[_ e] _]] e)
(defn west [[_ [w _]]] w)
(def unit-movements {"N" [[1 0] [0 0]]
"E" [[0 1] [0 0]]
"S" [[0 0] [0 1]]
"W" [[0 0] [1 0]]})
(defn waypoint-movement [[action amount]]
(let [unit-movement (get unit-movements action)]
(map (partial map (partial * amount)) unit-movement)))
(defn apply-waypoint-movement [waypoint movement]
(map (partial map +) waypoint movement))
(defn rotate-waypoint [waypoint rotation degrees]
(let [rotations (mod (/ degrees 90) 4)]
(last (take (inc rotations) (iterate rotation waypoint)))))
(defn step-both [state [action amount]]
(case action
"N" (update state :waypoint apply-waypoint-movement (waypoint-movement [action amount]))
"S" (update state :waypoint apply-waypoint-movement (waypoint-movement [action amount]))
"E" (update state :waypoint apply-waypoint-movement (waypoint-movement [action amount]))
"W" (update state :waypoint apply-waypoint-movement (waypoint-movement [action amount]))
"L" (update state :waypoint rotate-waypoint rotate-left amount)
"R" (update state :waypoint rotate-waypoint rotate-right amount)
"F" (let [waypoint (:waypoint state)]
(-> state
(step-ship ["N" (* amount (north waypoint))])
(step-ship ["E" (* amount (east waypoint))])
(step-ship ["S" (* amount (south waypoint))])
(step-ship ["W" (* amount (west waypoint))])))))
(defn first-answer []
(let [{x :x y :y} (reduce step-ship {:x 0 :y 0 :direction "E"} (read-directions)))]
(+ (Math/abs x) (Math/abs y))))
(defn second-answer []
(let [{x :x y :y} (reduce step-both {:x 0 :y 0 :waypoint [[1 10] [0 0]]} (read-directions))]
(+ (Math/abs x) (Math/abs y))))