]>
Commit | Line | Data |
---|---|---|
d0f13cd2 JK |
1 | (ns adventofcode2019.day07 |
2 | [:require [adventofcode2019.lib :refer :all] | |
3 | [clojure.string :as str] | |
4 | [clojure.math.combinatorics :as combo]]) | |
5 | ||
6 | ;; a slightly less awful hack | |
7 | (def phase-setting (atom [nil 0 nil nil nil nil | |
8 | nil nil nil nil nil nil])) | |
9 | (defn get-phase-setting [] | |
10 | (let [input (first @phase-setting)] | |
11 | (swap! phase-setting subvec 1) | |
12 | input)) | |
13 | (defn put-phase-setting [input] | |
14 | (swap! phase-setting assoc 1 input)) | |
15 | ||
16 | ;; 0: function args&mem -> [mem (ctr -> ctr)] | |
17 | ;; 1: number of args | |
18 | (def operations {1 [(fn [a b c mem] | |
19 | [(assoc mem c (+ a b)) #(+ % 4)]) | |
20 | 3] | |
21 | 2 [(fn [a b c mem] | |
22 | [(assoc mem c (* a b)) #(+ % 4)]) | |
23 | 3] | |
24 | 3 [(fn [a mem] | |
25 | [(assoc mem a (get-phase-setting)) #(+ % 2)]) | |
26 | 1] | |
27 | 4 [(fn [a mem] | |
28 | (put-phase-setting (mem a)) | |
29 | [mem #(+ % 2)]) | |
30 | 1] | |
31 | 5 [(fn [a b mem] | |
32 | [mem (if (not= a 0) (constantly b) #(+ % 3))]) | |
33 | 2] | |
34 | 6 [(fn [a b mem] | |
35 | [mem (if (= a 0) (constantly b) #(+ % 3))]) | |
36 | 2] | |
37 | 7 [(fn [a b c mem] | |
38 | [(assoc mem c (if (< a b) 1 0)) #(+ % 4)]) | |
39 | 3] | |
40 | 8 [(fn [a b c mem] | |
41 | [(assoc mem c (if (= a b) 1 0)) #(+ % 4)]) | |
42 | 3]}) | |
43 | ||
44 | ;; FIXME: sorry about the dropped forms i didn't want to fix it properly | |
45 | ;; the problem is that flags don't apply to certain args for certain ops | |
46 | (defn decode-op [opcode] | |
47 | (let [str-code (format "%05d" opcode) | |
48 | [f3 f2 f1] (map #(= \1 %) (take 3 str-code)) | |
49 | op (parse-int (str/join (drop 3 str-code))) | |
50 | [operation arg-ct] (operations op)] | |
51 | [(case arg-ct | |
52 | 1 #(operation #_((if f1 identity %1) %2) %2 %1) | |
53 | 2 #(operation ((if f1 identity %1) %2) | |
54 | ((if f2 identity %1) %3) %1) | |
55 | 3 #(operation ((if f1 identity %1) %2) | |
56 | ((if f2 identity %1) %3) | |
57 | #_((if f3 identity %1) %4) %4 %1)) | |
58 | arg-ct])) | |
59 | ||
60 | (defn perform-operation [program counter] | |
61 | (let [opcode (program counter) | |
62 | [operation arg-ct] (decode-op opcode) | |
63 | args (->> (iterate inc counter) | |
64 | (rest) | |
65 | (take arg-ct) | |
66 | (map program))] | |
67 | (let [[program ctr-update] (apply operation program args)] | |
68 | [program (ctr-update counter)]))) | |
69 | ||
70 | (defn intcode [program] | |
71 | (loop [[program counter] [program 0]] | |
72 | (let [opcode (program counter)] | |
73 | (if (= opcode 99) | |
74 | program | |
75 | (recur (perform-operation program counter)))))) | |
76 | ||
77 | (defn day07 [] | |
78 | (let [input (mapv parse-int (get-list-from-file (input-file) #",")) | |
79 | phase-settings (combo/permutations [0 1 2 3 4]) | |
80 | all-outputs (for [[a b c d e] phase-settings] | |
81 | (do (reset! phase-setting [a 0 b nil c nil d nil e nil nil nil]) | |
82 | (dotimes [_ 5] (intcode input)) | |
83 | (last @phase-setting)))] | |
84 | (part1 (apply max all-outputs)) | |
85 | #_(part2 ))) |