(ns adventofcode2019.day14 [:require [adventofcode2019.lib :refer :all] [clojure.string :as str] [clojure.core.match :refer [match]]]) (defn parse-reaction [reaction-text] (let [parse-chemical (fn [text] (let [[ct chem] (str/split (str/trim text) #" ")] {chem (parse-int ct)})) [inputs output] (str/split reaction-text #"=>") [[out-chem out-ct]] (seq (parse-chemical output))] {out-chem [(reduce merge {} (map parse-chemical (str/split inputs #","))) out-ct]})) (defn make-graph [input] (reduce (partial merge-with merge) (map parse-reaction input))) (defn reduce-reaction [graph producing consuming] (let [consuming (into #{} (if (coll? consuming) consuming [consuming])) [inputs moles] (graph producing) in-chems (keys inputs) replace-term (fn [chem] (if (or (contains? consuming chem) (neg? (second (graph chem)))) {chem (inputs chem)} (let [ch-req (inputs chem) [ch-in ch-mo] (graph chem) conversion (int (Math/ceil (/ ch-req ch-mo)))] (assoc (mmap (partial * conversion) ch-in) chem (- ch-req (* ch-mo conversion)))))) check-reduced (fn [[ch ct]] (and (not (contains? consuming ch)) (pos? ct))) reduced-inputs (reduce (partial merge-with +) (map replace-term in-chems)) new-graph (assoc graph producing [reduced-inputs moles])] (if (some check-reduced reduced-inputs) (recur new-graph producing consuming) new-graph))) (defn find-lowest-exchange-rate [graph producing consuming] (get-in (reduce-reaction graph producing consuming) [producing 0 consuming])) (defn produce-with [graph producing consuming cargo] (println graph producing consuming cargo) (let [cheapest-prod (get-in graph [producing 0]) exchange-rate (cheapest-prod consuming) base-times (quot cargo exchange-rate) extra-cargo (mod cargo exchange-rate) extra-resources (assoc (->> cheapest-prod (filter (comp neg? second)) (map (fn [[chem mole]] [chem (* -1 base-times mole)])) (into {})) consuming extra-cargo) rewrite-with (into #{} (keys extra-resources)) second-chance (reduce-reaction graph producing rewrite-with) recursive-times (map (fn [[chem ct]] (let [er (- (get-in second-chance [producing 0 chem]))] (println chem ct er) (quot ct er))) extra-resources)] recursive-times)) (defn maximize-output [graph producing consuming cargo] (produce-with (reduce-reaction graph producing consuming) producing consuming cargo)) (defn day14 [] (let [graphed (make-graph (get-list-from-file (input-file)))] (part1 (find-lowest-exchange-rate graphed "FUEL" "ORE")) (part2 (maximize-output graphed "FUEL" "ORE" 1000000000000))))