Add correct day7pt1
[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
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 )))