1 (ns adventofcode2019.day07
2 [:require [adventofcode2019.lib :refer :all]
3 [clojure.string :as str]
4 [clojure.math.combinatorics :as combo]])
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)
13 (defn put-phase-setting [input]
14 (swap! phase-setting assoc 1 input))
16 ;; 0: function args&mem -> [mem (ctr -> ctr)]
18 (def operations {1 [(fn [a b c mem]
19 [(assoc mem c (+ a b)) #(+ % 4)])
22 [(assoc mem c (* a b)) #(+ % 4)])
25 [(assoc mem a (get-phase-setting)) #(+ % 2)])
28 (put-phase-setting (mem a))
32 [mem (if (not= a 0) (constantly b) #(+ % 3))])
35 [mem (if (= a 0) (constantly b) #(+ % 3))])
38 [(assoc mem c (if (< a b) 1 0)) #(+ % 4)])
41 [(assoc mem c (if (= a b) 1 0)) #(+ % 4)])
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)]
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))
60 (defn perform-operation [program counter]
61 (let [opcode (program counter)
62 [operation arg-ct] (decode-op opcode)
63 args (->> (iterate inc counter)
67 (let [[program ctr-update] (apply operation program args)]
68 [program (ctr-update counter)])))
70 (defn intcode [program]
71 (loop [[program counter] [program 0]]
72 (let [opcode (program counter)]
75 (recur (perform-operation program counter))))))
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))