]>
Commit | Line | Data |
---|---|---|
d0f13cd2 JK |
1 | (ns adventofcode2019.day07 |
2 | [:require [adventofcode2019.lib :refer :all] | |
3 | [clojure.string :as str] | |
9a22e14c JK |
4 | [clojure.math.combinatorics :as combo] |
5 | [clojure.core.async :as a]]) | |
d0f13cd2 JK |
6 | |
7 | ;; 0: function args&mem -> [mem (ctr -> ctr)] | |
8 | ;; 1: number of args | |
9a22e14c | 9 | (defn decode-op [opcode in out] |
d0f13cd2 JK |
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))) | |
9a22e14c JK |
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])))) | |
d0f13cd2 | 47 | |
9a22e14c | 48 | (defn perform-operation [program counter in out] |
d0f13cd2 | 49 | (let [opcode (program counter) |
9a22e14c | 50 | [operation arg-ct] (decode-op opcode in out) |
d0f13cd2 JK |
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 | ||
9a22e14c JK |
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))))))) | |
d0f13cd2 JK |
67 | |
68 | (defn day07 [] | |
69 | (let [input (mapv parse-int (get-list-from-file (input-file) #",")) | |
9a22e14c JK |
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)))) |