--- /dev/null
+3,8,1001,8,10,8,105,1,0,0,21,34,47,72,93,110,191,272,353,434,99999,3,9,102,3,9,9,1001,9,3,9,4,9,99,3,9,102,4,9,9,1001,9,4,9,4,9,99,3,9,101,3,9,9,1002,9,3,9,1001,9,2,9,1002,9,2,9,101,4,9,9,4,9,99,3,9,1002,9,3,9,101,5,9,9,102,4,9,9,1001,9,4,9,4,9,99,3,9,101,3,9,9,102,4,9,9,1001,9,3,9,4,9,99,3,9,101,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,99,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,2,9,9,4,9,99,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,2,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,99,3,9,101,1,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,99
--- /dev/null
+(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 )))