(ns adventofcode2019.day13 [:require [adventofcode2019.lib :refer :all] [adventofcode2019.intcode :as i] [clojure.string :as str] [clojure.core.match :refer [match]] [clojure.math.combinatorics :as combo] [lanterna.terminal :as ts]]) (def term (ts/get-terminal :text)) (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 term] (let [to-text #(case % 0 \space 1 \| 2 \- 3 \_ 4 \O) paint-tile (fn [[[x y] tile]] (ts/move-cursor term x y) (ts/put-character term (to-text tile)))] (doall (map paint-tile tiles)))) (defn print-field [field score] (run! (comp println str/join) field) (println score) (flush)) (defn run-game [game [[min-x max-x] [min-y max-y]]] (let [wait-for-output #(= (count (:output %)) 3) get-next-ic-output (partial i/intcode-until wait-for-output) new-game (assoc game :input [0]) field (ts/get-terminal :swing)] (ts/start field) (ts/put-character field \a) (loop [program-state (get-next-ic-output new-game) score 0 framerate 0 ctr 0] (Thread/sleep framerate) (if (:exit program-state) (do (ts/stop field) score) (let [[x y t] (:output program-state) [new-score new-screen] (if (and (= x -1) (= y 0)) [t {}] [score {[x y] t}]) input (case (ts/get-key-blocking field {:interval 1 :timeout framerate}) \a -1 \d 1 0)] (draw-tiles new-screen field) (recur (get-next-ic-output (assoc program-state :output [] :input [input])) new-score (if (> ctr 814) 100 0) (inc ctr))))))) (defn day13 [] (let [input (i/get-program (input-file)) output (:output (i/intcode (i/build-state input))) draw-tiles (fn [screen [x y t]] (assoc screen [x y] t)) screen (reduce draw-tiles {} (partition 3 output)) game (assoc-in (i/build-state input {:step true}) [:memory 0] 2)] (part1 (count (filter #(= % 2) (vals screen)))) (part2 (run-game game (find-bounds screen)))))