ref: master
2020/src/aoc/day12.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 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
(ns aoc.day12 (:require [clojure.java.io :as io])) (def example "F10 N3 F7 R90 F11") (def start-pos {:facing :east :north 0 :east 0}) (def start-pos-2 {:wp {:north 1 :east 10} :ship {:north 0 :east 0}}) (defn translate [direction [x y]] (case direction :right [y (- x)] :left [(- y) x])) (defn translate-wp [pos direction] (update-in pos [:wp] (fn [{:keys [north east]}] (let [[x y] (translate direction [east north])] {:north y :east x})))) (defn parse-inst [[h & body]] {:direction (case h \N :north \E :east \S :south \W :west \F :forward \L :left \R :right) :value (read-string (clojure.string/join body))}) (defn read-input [] (->> (io/resource "input12.txt") slurp ;; example clojure.string/split-lines (map parse-inst) )) (defn move [direction value] (fn [old] (let [op (case direction :north + :south - :east + :west -)] (if (nil? op) old (op old value))))) (def right-turns (cycle [:east :south :west :north])) (def left-turns (cycle [:east :north :west :south])) (defn turn-count [n] (case n 90 1 180 2 270 3 0 0)) (defn turn [pos {:keys [value direction]}] (let [current-direction (:facing pos) tc (turn-count value) turns (case direction :left left-turns :right right-turns []) next-turns (drop-while #(not= current-direction %) turns)] (nth next-turns tc))) (defn move-forward [pos {:keys [value direction]}] (let [facing (:facing pos) op (case facing :north + :east + :south - :west -)] (if (contains? #{:north :south} facing) (assoc pos :north (op (:north pos) value)) (assoc pos :east (op (:east pos) value))))) (defn navigate [pos {:keys [value direction]}] (case direction :north (update pos :north (move direction value)) :south (update pos :north (move direction value)) :east (update pos :north (move direction value)) :west (update pos :north (move direction value)) :left (assoc pos :facing (turn pos {:direction direction :value value})) :right (assoc pos :facing (turn pos {:direction direction :value value})) :forward (move-forward pos {:direction direction :value value}) pos)) (defn should-move-wp? [direction] (not= direction :forward)) (defn should-move-ship? [direction] (= direction :forward)) (defn move-ship [pos {:keys [value]}] (let [wx (get-in pos [:wp :east]) wy (get-in pos [:wp :north]) pos (update-in pos [:ship :east] #(+ % (* wx value))) pos (update-in pos [:ship :north] #(+ % (* wy value)))] pos)) ;; (move-ship {:wp {:east -1 :north -2} :ship {:east 1 :north 1}} ;; {:value 0}) (defn rotate-wp [pos {:keys [value direction]}] (let [tc (turn-count value)] (reduce (fn [acc _] (translate-wp acc direction)) pos (range tc)))) (defn move-wp [pos {:keys [value direction] :as i}] (case direction :north (update-in pos [:wp :north] #(+ % value)) :south (update-in pos [:wp :north] #(- % value)) :east (update-in pos [:wp :east ] #(+ % value)) :west (update-in pos [:wp :east ] #(- % value)) :right (rotate-wp pos i) :left (rotate-wp pos i))) (defn navigate-2 [pos {:keys [value direction] :as i}] (cond (should-move-wp? direction) (move-wp pos i) (should-move-ship? direction) (move-ship pos i) :else pos)) (defn compute-1 [input] (let [final (reduce navigate start-pos input)] (+ (Math/abs (:north final)) (Math/abs (:east final))))) (defn compute-2 [input] (let [final (reduce navigate-2 start-pos-2 input)] (+ (Math/abs (get-in final [:ship :north])) (Math/abs (get-in final [:ship :east]))))) (defn main [] (let [input (read-input)] (println (compute-1 input)) (println (compute-2 input)))) (main) |