[clojure.string :as str]
[clojure.core.match :refer [match]]])
-(defn painterbot-9000 [program]
+(defn painterbot-9000 [program input]
(let [stop-on-output #(= (count (:output %)) 2)
get-next-ic-output (partial i/intcode-until stop-on-output)
+ start-state (i/build-state program {:input [input]})
rotate (fn [heading turning]
(match [heading turning]
[:up 0] :left
[:right 0] :up
[:up 1] :right
[:down 1] :left
- [:left 1] :down
- [:right 1] :up))
+ [:left 1] :up
+ [:right 1] :down))
travel (fn [[x y] heading]
(case heading
- :up [x (inc y)]
- :down [x (dec y)]
+ :up [x (dec y)]
+ :down [x (inc y)]
:left [(dec x) y]
:right [(inc x) y]))]
- (loop [program-state (i/build-state program {:input [0]})
+ (loop [program-state (get-next-ic-output start-state)
tileset {}
position [0 0]
heading :up]
(if (:exit program-state)
tileset
- (let [next-state (get-next-ic-output program-state)
- [color direction] (:output next-state)
- new-heading (rotate heading direction)]
- (recur (assoc next-state :output []) (assoc tileset position color)
- (travel position new-heading) new-heading))))))
+ (let [[color direction] (:output program-state)
+ new-heading (rotate heading direction)
+ new-position (travel position new-heading)
+ prep-state (assoc program-state
+ :output []
+ :input [(get tileset new-position 0)])]
+ (recur (get-next-ic-output prep-state)
+ (assoc tileset position color)
+ new-position new-heading))))))
+
+(defn find-bounds [tiles]
+ (let [x-list (map first (keys tiles))
+ y-list (map second (keys tiles))
+ min-x (reduce min x-list)
+ max-x (reduce max x-list)
+ min-y (reduce min y-list)
+ max-y (reduce max y-list)]
+ [[min-x max-x] [min-y max-y]]))
+
+(defn make-field [[dx dy]]
+ (let [line (vec (repeat dx \space))]
+ (mapv (constantly line) (range dy))))
+
+(defn draw-tiles [tiles]
+ (let [[[min-x max-x] [min-y max-y]] (find-bounds tiles)
+ to-text #(match % 0 \space
+ 1 \u2588) ; full-block
+ field (make-field [(- max-x min-x -1) (- max-y min-y -1)])
+ paint-tile (fn [field [x y] color]
+ (assoc-in field [(- y min-y) (- x min-x)] (to-text color)))]
+ (mapv str/join (reduce-kv paint-tile field tiles))))
(defn day11 []
(let [input (mapv parse-int (get-list-from-file (input-file) #","))
- painted-tiles (painterbot-9000 input)]
+ painted-tiles (painterbot-9000 input 0)
+ reg-id-tiles (painterbot-9000 input 1)]
(part1 (count painted-tiles))
- #_(part2)))
+ (part2 "see below")
+ (run! println (draw-tiles reg-id-tiles))))
[\0 \3] (fn [S a _ _] ; IN
(-> S
(assoc-in [:memory (a S true)] (first (:input S)))
- (update :input subvec 1)
+ (update :input rest)
(update :ctr + 2)))
[\0 \4] (fn [S a _ _] ; OUT
(-> S
- (update :output conj (or (get-in S [:memory (a S true)]) 0))
+ (update :output conj (a S))
(update :ctr + 2)))
[\0 \5] (fn [S a b _] ; BNEQ
(update S :ctr (if (not= (a S) 0) (constantly (b S)) #(+ % 3))))
([program settings]
(merge (build-state program) settings)))
+(defn intcode [{:as state :keys [memory output]}]
+ (cond ; quit if :exit, step and return state if :step, else loop
+ (get state :exit) {:memory memory :output output :exit true}
+ (get state :step) (perform-operation state)
+ :else (recur (perform-operation state))))
+
(defn intcode-until [pred state]
(as-> (assoc state :step true) it
(iterate intcode it)
- (drop-while #(or (not (:exit %)) (pred %)) it)
+ (drop-while #(not (or (:exit %) (pred %))) it)
(first it)
(dissoc it :step)))
-
-(defn intcode [{:as state :keys [memory output]}]
- (cond ; quit if :exit, step and return state if :step, else loop
- (get state :exit) {:memory memory :output output :exit true}
- (get state :step) (perform-operation state)
- :else (recur (perform-operation state))))