diff --git a/2024/.gitignore b/2024/.gitignore new file mode 100644 index 0000000..6436383 --- /dev/null +++ b/2024/.gitignore @@ -0,0 +1 @@ +input/ diff --git a/2024/src/day24.clj b/2024/src/day24.clj new file mode 100644 index 0000000..dd6b2ee --- /dev/null +++ b/2024/src/day24.clj @@ -0,0 +1,126 @@ +(ns day24 + (:require + [clojure.math :as math] + [clojure.string :as s] + [core :as c :refer :all] + [input-manager :as i])) + +(def sample "x00: 1 +x01: 0 +x02: 1 +x03: 1 +x04: 0 +y00: 1 +y01: 1 +y02: 1 +y03: 1 +y04: 1 + +ntg XOR fgs -> mjb +y02 OR x01 -> tnw +kwq OR kpj -> z05 +x00 OR x03 -> fst +tgd XOR rvg -> z01 +vdt OR tnw -> bfw +bfw AND frj -> z10 +ffh OR nrd -> bqk +y00 AND y03 -> djm +y03 OR y00 -> psh +bqk OR frj -> z08 +tnw OR fst -> frj +gnj AND tgd -> z11 +bfw XOR mjb -> z00 +x03 OR x00 -> vdt +gnj AND wpb -> z02 +x04 AND y00 -> kjc +djm OR pbm -> qhw +nrd AND vdt -> hwm +kjc AND fst -> rvg +y04 OR y02 -> fgs +y01 AND x02 -> pbm +ntg OR kjc -> kwq +psh XOR fgs -> tgd +qhw XOR tgd -> z09 +pbm OR djm -> kpj +x03 XOR y03 -> ffh +x00 XOR y04 -> ntg +bfw OR bqk -> z06 +nrd XOR fgs -> wpb +frj XOR qhw -> z04 +bqk OR frj -> z07 +y03 OR x01 -> nrd +hwm AND bqk -> z03 +tgd XOR rvg -> z12 +tnw OR pbm -> gnj") + +(let [[a b] (c/split-on-double-newlines + (i/get-input-raw 2024 24) + ; sample + ; + )] + (def registers (->> (s/split-lines a) + (map #(c/get-match-groups #"^(.*): (.*)$" %)) + (map first) + (map vec) + (into {}) + (#(update-vals % parse-long)))) + (def instrs (->> (s/split-lines b) + (map c/split-whitespace) + (map (fn [[a op b _ out]] + {:args #{a b} + :op op + :out out})) + (group-by :out) + (#(update-vals % first))))) + +(defn get-var [prefix tape] + (->> (filter (fn [[reg value]] + (s/starts-with? reg prefix)) + tape) + sort + reverse + (map second) + (s/join))) + +(defn get-op-fn [op] + (condp = op + "AND" bit-and + "OR" bit-or + "XOR" bit-xor)) + +;; part 1 +(->> (loop [tape registers + q (vec instrs)] + (if (empty? q) + tape + (let [[out curr :as instr] (first q) + {:keys [args op]} curr + operands (map (juxt identity tape) args) + to-be-computed (filter #(nil? (second %)) operands) + q' (subvec q 1)] + (cond + ;; already computed + (tape out) (recur tape q') + + ;; needs dep + (seq to-be-computed) (recur tape + (-> q' + (conj instr))) + + ;; ready to compute + :else (recur (assoc tape out (apply (get-op-fn op) + (map second operands))) + q'))))) + + (get-var "z") + binary->long) + +;; part 2 +;; output of machine should be +(->> ["x" "y"] + (map #(get-var % registers)) + (map binary->long) + (apply +) + long->binary) + +;; find what gates need to be flipped such that part 1 outputs that num