Add extremely broken day14pt2
[adventofcode2019.git] / src / adventofcode2019 / day07.clj
1 (ns adventofcode2019.day07
2 [:require [adventofcode2019.lib :refer :all]
3 [clojure.string :as str]
4 [clojure.math.combinatorics :as combo]
5 [clojure.core.async :as a]])
6
7 ;; 0: function args&mem -> [mem (ctr -> ctr)]
8 ;; 1: number of args
9 (defn decode-op [opcode in out]
10 (let [str-code (format "%05d" opcode)
11 [f3 f2 f1] (map #(= \1 %) (take 3 str-code))
12 op (parse-int (str/join (drop 3 str-code)))
13 with-flags (fn [[f ac]]
14 [(case ac
15 1 #(f %2 %1)
16 2 #(f ((if f1 identity %1) %2)
17 ((if f2 identity %1) %3) %1)
18 3 #(f ((if f1 identity %1) %2)
19 ((if f2 identity %1) %3) %4 %1)) ac])]
20 (with-flags
21 (case op
22 1 [(fn [a b c mem]
23 [(assoc mem c (+ a b)) #(+ % 4)])
24 3]
25 2 [(fn [a b c mem]
26 [(assoc mem c (* a b)) #(+ % 4)])
27 3]
28 3 [(fn [a mem]
29 [(assoc mem a (a/<!! in)) #(+ % 2)])
30 1]
31 4 [(fn [a mem]
32 (a/>!! out (mem a))
33 [mem #(+ % 2)])
34 1]
35 5 [(fn [a b mem]
36 [mem (if (not= a 0) (constantly b) #(+ % 3))])
37 2]
38 6 [(fn [a b mem]
39 [mem (if (= a 0) (constantly b) #(+ % 3))])
40 2]
41 7 [(fn [a b c mem]
42 [(assoc mem c (if (< a b) 1 0)) #(+ % 4)])
43 3]
44 8 [(fn [a b c mem]
45 [(assoc mem c (if (= a b) 1 0)) #(+ % 4)])
46 3]))))
47
48 (defn perform-operation [program counter in out]
49 (let [opcode (program counter)
50 [operation arg-ct] (decode-op opcode in out)
51 args (->> (iterate inc counter)
52 (rest)
53 (take arg-ct)
54 (map program))]
55 (let [[program ctr-update] (apply operation program args)]
56 [program (ctr-update counter)])))
57
58 (defn intcode
59 ([program]
60 (intcode program nil nil))
61 ([program in out]
62 (loop [[program counter] [program 0]]
63 (let [opcode (program counter)]
64 (if (= opcode 99)
65 program
66 (recur (perform-operation program counter in out)))))))
67
68 (defn day07 []
69 (let [input (mapv parse-int (get-list-from-file (input-file) #","))
70 phase-settings-1 (combo/permutations [0 1 2 3 4])
71 phase-settings-2 (combo/permutations [5 6 7 8 9])
72 channels (->> #(a/chan 2)
73 (repeatedly 5)
74 (cycle))
75 all-outputs-1 (for [settings phase-settings-1]
76 (do (doall (map a/>!! channels settings))
77 (a/>!! (first channels) 0)
78 (doall (map intcode (repeat 5 input) channels (rest channels)))
79 (a/<!! (first channels))))
80 all-outputs-2 (for [settings phase-settings-2]
81 (do (doall (map a/>!! channels settings))
82 (a/>!! (first channels) 0)
83 (a/<!! (last (for [[prog in out]
84 (map vector (repeat 5 input) channels (rest channels))]
85 (a/thread
86 (intcode prog in out)))))
87 (a/<!! (first channels))))]
88 (part1 (apply max all-outputs-1))
89 (part2 (apply max all-outputs-2))))