]> localhost Git - adventofcode2019.git/blobdiff - src/adventofcode2019/day07.clj
Add correct day7pt1
[adventofcode2019.git] / src / adventofcode2019 / day07.clj
diff --git a/src/adventofcode2019/day07.clj b/src/adventofcode2019/day07.clj
new file mode 100644 (file)
index 0000000..9b43cc4
--- /dev/null
@@ -0,0 +1,85 @@
+(ns adventofcode2019.day07
+    [:require [adventofcode2019.lib :refer :all]
+              [clojure.string :as str]
+              [clojure.math.combinatorics :as combo]])
+
+;; a slightly less awful hack
+(def phase-setting (atom [nil 0 nil nil nil nil 
+                          nil nil nil nil nil nil]))
+(defn get-phase-setting []
+  (let [input (first @phase-setting)]
+    (swap! phase-setting subvec 1)
+    input))
+(defn put-phase-setting [input]
+  (swap! phase-setting assoc 1 input))
+
+;; 0: function args&mem -> [mem (ctr -> ctr)]
+;; 1: number of args
+(def operations {1 [(fn [a b c mem]
+                        [(assoc mem c (+ a b)) #(+ % 4)])
+                    3] 
+                 2 [(fn [a b c mem]
+                        [(assoc mem c (* a b)) #(+ % 4)])
+                    3] 
+                 3 [(fn [a mem] 
+                        [(assoc mem a (get-phase-setting)) #(+ % 2)])
+                    1]
+                 4 [(fn [a mem] 
+                        (put-phase-setting (mem a)) 
+                        [mem #(+ % 2)]) 
+                    1]
+                 5 [(fn [a b mem]
+                        [mem (if (not= a 0) (constantly b) #(+ % 3))])
+                    2]
+                 6 [(fn [a b mem]
+                        [mem (if (= a 0) (constantly b) #(+ % 3))])
+                    2]
+                 7 [(fn [a b c mem]
+                        [(assoc mem c (if (< a b) 1 0)) #(+ % 4)])
+                    3]
+                 8 [(fn [a b c mem]
+                        [(assoc mem c (if (= a b) 1 0)) #(+ % 4)])
+                    3]})
+
+;; FIXME: sorry about the dropped forms i didn't want to fix it properly
+;; the problem is that flags don't apply to certain args for certain ops
+(defn decode-op [opcode] 
+  (let [str-code (format "%05d" opcode)
+        [f3 f2 f1] (map #(= \1 %) (take 3 str-code))
+        op (parse-int (str/join (drop 3 str-code)))
+        [operation arg-ct] (operations op)]
+    [(case arg-ct
+       1 #(operation #_((if f1 identity %1) %2) %2 %1)
+       2 #(operation ((if f1 identity %1) %2) 
+                     ((if f2 identity %1) %3) %1)
+       3 #(operation ((if f1 identity %1) %2) 
+                     ((if f2 identity %1) %3) 
+                     #_((if f3 identity %1) %4) %4 %1)) 
+     arg-ct]))
+
+(defn perform-operation [program counter]
+   (let [opcode (program counter)
+         [operation arg-ct] (decode-op opcode)
+         args (->> (iterate inc counter) 
+                   (rest) 
+                   (take arg-ct) 
+                   (map program))]
+     (let [[program ctr-update] (apply operation program args)]
+       [program (ctr-update counter)])))
+
+(defn intcode [program]
+  (loop [[program counter] [program 0]]
+    (let [opcode (program counter)]
+      (if (= opcode 99)
+        program
+        (recur (perform-operation program counter))))))
+
+(defn day07 []
+  (let [input (mapv parse-int (get-list-from-file (input-file) #","))
+        phase-settings (combo/permutations [0 1 2 3 4])
+        all-outputs (for [[a b c d e] phase-settings]
+                         (do (reset! phase-setting [a 0 b nil c nil d nil e nil nil nil])
+                             (dotimes [_ 5] (intcode input))
+                             (last @phase-setting)))]
+    (part1 (apply max all-outputs)) 
+    #_(part2 )))