Commit | Line | Data |
---|---|---|
15f6c3bb JK |
1 | (ns adventofcode2019.day13 |
2 | [:require [adventofcode2019.lib :refer :all] | |
3 | [adventofcode2019.intcode :as i] | |
4 | [clojure.string :as str] | |
5 | [clojure.core.match :refer [match]] | |
ab32e543 JK |
6 | [lanterna.terminal :as ts]]) |
7 | ||
ab32e543 JK |
8 | (defn find-bounds [tiles] |
9 | (let [x-list (map first (keys tiles)) | |
10 | y-list (map second (keys tiles)) | |
11 | min-x (reduce min x-list) | |
12 | max-x (reduce max x-list) | |
13 | min-y (reduce min y-list) | |
14 | max-y (reduce max y-list)] | |
15 | [[min-x max-x] [min-y max-y]])) | |
16 | ||
17 | (defn make-field [[dx dy]] | |
18 | (let [line (vec (repeat dx \space))] | |
19 | (mapv (constantly line) (range dy)))) | |
20 | ||
21 | (defn draw-tiles [tiles term] | |
22 | (let [to-text #(case % | |
23 | 0 \space | |
24 | 1 \| | |
25 | 2 \- | |
26 | 3 \_ | |
27 | 4 \O) | |
28 | paint-tile (fn [[[x y] tile]] | |
29 | (ts/move-cursor term x y) | |
30 | (ts/put-character term (to-text tile)))] | |
31 | (doall (map paint-tile tiles)))) | |
32 | ||
33 | (defn print-field [field score] | |
34 | (run! (comp println str/join) field) | |
35 | (println score) | |
36 | (flush)) | |
37 | ||
b7447f5a JK |
38 | (defn find-next-paddle-contact [screen prev-ball ball paddle] |
39 | (let [db (map - ball prev-ball) | |
40 | [dx dy] db | |
41 | futr (take 50 (iterate (partial map + db) ball)) | |
42 | rdtn (fn [screen [bx by]] | |
43 | (if (or (= by paddle) (= dx 0)) | |
44 | (reduced bx) | |
45 | (reduced bx) | |
46 | #_(case (screen [bx by]) | |
47 | 1 (find-next-paddle-contact screen [bx by] [(- bx dx) by] paddle) | |
48 | 2 (find-next-paddle-contact screen [bx by] [(+ bx dx) (dec by)] paddle) | |
49 | screen))) | |
50 | px (reduce rdtn screen futr)] | |
51 | (if (= px screen) 0 px))) | |
52 | ||
ab32e543 JK |
53 | (defn run-game [game [[min-x max-x] [min-y max-y]]] |
54 | (let [wait-for-output #(= (count (:output %)) 3) | |
55 | get-next-ic-output (partial i/intcode-until wait-for-output) | |
56 | new-game (assoc game :input [0]) | |
57 | field (ts/get-terminal :swing)] | |
b7447f5a | 58 | #_(ts/start field) |
ab32e543 | 59 | (loop [program-state (get-next-ic-output new-game) |
b7447f5a | 60 | screen {} |
ab32e543 JK |
61 | score 0 |
62 | framerate 0 | |
b7447f5a JK |
63 | ctr 0 |
64 | prev-ball nil | |
65 | ball nil | |
66 | paddle nil | |
67 | joyst 1] | |
68 | #_(Thread/sleep framerate) | |
ab32e543 | 69 | (if (:exit program-state) |
b7447f5a | 70 | (do #_(ts/stop field) |
ab32e543 JK |
71 | score) |
72 | (let [[x y t] (:output program-state) | |
73 | [new-score new-screen] (if (and (= x -1) (= y 0)) | |
b7447f5a JK |
74 | (do #_(ts/move-cursor field x y) |
75 | #_(ts/put-string field (str t)) | |
76 | [t {}]) | |
ab32e543 | 77 | [score {[x y] t}]) |
b7447f5a JK |
78 | screen (merge screen new-screen) |
79 | #_(case (ts/get-key-blocking field {:interval framerate | |
80 | :timeout framerate}) | |
ab32e543 JK |
81 | \a -1 |
82 | \d 1 | |
b7447f5a JK |
83 | 0) |
84 | paddle (if (= t 3) [x y] paddle) | |
85 | prev-ball (if (= t 4) ball prev-ball) | |
86 | ball (if (= t 4) [x y] ball) | |
87 | joyst (if (and prev-ball ball paddle) | |
88 | (compare (find-next-paddle-contact screen prev-ball ball (second paddle)) (first paddle)))] | |
89 | #_(draw-tiles new-screen field) | |
ab32e543 JK |
90 | (recur (get-next-ic-output (assoc program-state |
91 | :output [] | |
b7447f5a JK |
92 | :input [joyst])) |
93 | screen new-score 0 #_(if (> ctr 814) 0 0) (inc ctr) | |
94 | prev-ball ball paddle joyst)))))) | |
15f6c3bb JK |
95 | |
96 | (defn day13 [] | |
97 | (let [input (i/get-program (input-file)) | |
98 | output (:output (i/intcode (i/build-state input))) | |
99 | draw-tiles (fn [screen [x y t]] (assoc screen [x y] t)) | |
ab32e543 JK |
100 | screen (reduce draw-tiles {} (partition 3 output)) |
101 | game (assoc-in (i/build-state input {:step true}) [:memory 0] 2)] | |
102 | (part1 (count (filter #(= % 2) (vals screen)))) | |
103 | (part2 (run-game game (find-bounds screen))))) |