(ns adventofcode2019.day07 [:require [adventofcode2019.lib :refer :all] [clojure.string :as str] [clojure.math.combinatorics :as combo] [clojure.core.async :as a]]) ;; 0: function args&mem -> [mem (ctr -> ctr)] ;; 1: number of args (defn decode-op [opcode in out] (let [str-code (format "%05d" opcode) [f3 f2 f1] (map #(= \1 %) (take 3 str-code)) op (parse-int (str/join (drop 3 str-code))) with-flags (fn [[f ac]] [(case ac 1 #(f %2 %1) 2 #(f ((if f1 identity %1) %2) ((if f2 identity %1) %3) %1) 3 #(f ((if f1 identity %1) %2) ((if f2 identity %1) %3) %4 %1)) ac])] (with-flags (case op 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 (a/!! out (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])))) (defn perform-operation [program counter in out] (let [opcode (program counter) [operation arg-ct] (decode-op opcode in out) 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] (intcode program nil nil)) ([program in out] (loop [[program counter] [program 0]] (let [opcode (program counter)] (if (= opcode 99) program (recur (perform-operation program counter in out))))))) (defn day07 [] (let [input (mapv parse-int (get-list-from-file (input-file) #",")) phase-settings-1 (combo/permutations [0 1 2 3 4]) phase-settings-2 (combo/permutations [5 6 7 8 9]) channels (->> #(a/chan 2) (repeatedly 5) (cycle)) all-outputs-1 (for [settings phase-settings-1] (do (doall (map a/>!! channels settings)) (a/>!! (first channels) 0) (doall (map intcode (repeat 5 input) channels (rest channels))) (a/!! channels settings)) (a/>!! (first channels) 0) (a/