| 1 | (ns adventofcode2019.day11 |
| 2 | [:require [adventofcode2019.lib :refer :all] |
| 3 | [adventofcode2019.intcode :as i] |
| 4 | [clojure.string :as str] |
| 5 | [clojure.core.match :refer [match]]]) |
| 6 | |
| 7 | (defn painterbot-9000 [program input] |
| 8 | (let [stop-on-output #(= (count (:output %)) 2) |
| 9 | get-next-ic-output (partial i/intcode-until stop-on-output) |
| 10 | start-state (i/build-state program {:input [input]}) |
| 11 | rotate (fn [heading turning] |
| 12 | (match [heading turning] |
| 13 | [:up 0] :left |
| 14 | [:down 0] :right |
| 15 | [:left 0] :down |
| 16 | [:right 0] :up |
| 17 | [:up 1] :right |
| 18 | [:down 1] :left |
| 19 | [:left 1] :up |
| 20 | [:right 1] :down)) |
| 21 | travel (fn [[x y] heading] |
| 22 | (case heading |
| 23 | :up [x (dec y)] |
| 24 | :down [x (inc y)] |
| 25 | :left [(dec x) y] |
| 26 | :right [(inc x) y]))] |
| 27 | (loop [program-state (get-next-ic-output start-state) |
| 28 | tileset {} |
| 29 | position [0 0] |
| 30 | heading :up] |
| 31 | (if (:exit program-state) |
| 32 | tileset |
| 33 | (let [[color direction] (:output program-state) |
| 34 | new-heading (rotate heading direction) |
| 35 | new-position (travel position new-heading) |
| 36 | prep-state (assoc program-state |
| 37 | :output [] |
| 38 | :input [(get tileset new-position 0)])] |
| 39 | (recur (get-next-ic-output prep-state) |
| 40 | (assoc tileset position color) |
| 41 | new-position new-heading)))))) |
| 42 | |
| 43 | (defn find-bounds [tiles] |
| 44 | (let [x-list (map first (keys tiles)) |
| 45 | y-list (map second (keys tiles)) |
| 46 | min-x (reduce min x-list) |
| 47 | max-x (reduce max x-list) |
| 48 | min-y (reduce min y-list) |
| 49 | max-y (reduce max y-list)] |
| 50 | [[min-x max-x] [min-y max-y]])) |
| 51 | |
| 52 | (defn make-field [[dx dy]] |
| 53 | (let [line (vec (repeat dx \space))] |
| 54 | (mapv (constantly line) (range dy)))) |
| 55 | |
| 56 | (defn draw-tiles [tiles] |
| 57 | (let [[[min-x max-x] [min-y max-y]] (find-bounds tiles) |
| 58 | to-text #(match % 0 \space |
| 59 | 1 \u2588) ; full-block |
| 60 | field (make-field [(- max-x min-x -1) (- max-y min-y -1)]) |
| 61 | paint-tile (fn [field [x y] color] |
| 62 | (assoc-in field [(- y min-y) (- x min-x)] (to-text color)))] |
| 63 | (mapv str/join (reduce-kv paint-tile field tiles)))) |
| 64 | |
| 65 | (defn day11 [] |
| 66 | (let [input (mapv parse-int (get-list-from-file (input-file) #",")) |
| 67 | painted-tiles (painterbot-9000 input 0) |
| 68 | reg-id-tiles (painterbot-9000 input 1)] |
| 69 | (part1 (count painted-tiles)) |
| 70 | (part2 "see below") |
| 71 | (run! println (draw-tiles reg-id-tiles)))) |