| 1 | (ns adventofcode2019.day14 |
| 2 | [:require [adventofcode2019.lib :refer :all] |
| 3 | [clojure.string :as str] |
| 4 | [clojure.core.match :refer [match]]]) |
| 5 | |
| 6 | (defn parse-reaction [reaction-text] |
| 7 | (let [parse-chemical (fn [text] |
| 8 | (let [[ct chem] (str/split (str/trim text) #" ")] |
| 9 | {chem (parse-int ct)})) |
| 10 | [inputs output] (str/split reaction-text #"=>") |
| 11 | [[out-chem out-ct]] (seq (parse-chemical output))] |
| 12 | {out-chem [(reduce merge {} (map parse-chemical (str/split inputs #","))) out-ct]})) |
| 13 | |
| 14 | (defn make-graph [input] |
| 15 | (reduce (partial merge-with merge) |
| 16 | (map parse-reaction input))) |
| 17 | |
| 18 | (defn reduce-reaction [graph producing consuming] |
| 19 | (let [consuming (into #{} (if (coll? consuming) consuming [consuming])) |
| 20 | [inputs moles] (graph producing) |
| 21 | in-chems (keys inputs) |
| 22 | replace-term (fn [chem] |
| 23 | (if (or (contains? consuming chem) |
| 24 | (neg? (second (graph chem)))) |
| 25 | {chem (inputs chem)} |
| 26 | (let [ch-req (inputs chem) |
| 27 | [ch-in ch-mo] (graph chem) |
| 28 | conversion (int (Math/ceil (/ ch-req ch-mo)))] |
| 29 | (assoc (mmap (partial * conversion) ch-in) |
| 30 | chem (- ch-req (* ch-mo conversion)))))) |
| 31 | check-reduced (fn [[ch ct]] (and (not (contains? consuming ch)) (pos? ct))) |
| 32 | reduced-inputs (reduce (partial merge-with +) |
| 33 | (map replace-term in-chems)) |
| 34 | new-graph (assoc graph producing [reduced-inputs moles])] |
| 35 | (if (some check-reduced reduced-inputs) |
| 36 | (recur new-graph producing consuming) |
| 37 | new-graph))) |
| 38 | |
| 39 | (defn find-lowest-exchange-rate [graph producing consuming] |
| 40 | (get-in (reduce-reaction graph producing consuming) |
| 41 | [producing 0 consuming])) |
| 42 | |
| 43 | (defn produce-with [graph producing consuming cargo] |
| 44 | (println graph producing consuming cargo) |
| 45 | (let [cheapest-prod (get-in graph [producing 0]) |
| 46 | exchange-rate (cheapest-prod consuming) |
| 47 | base-times (quot cargo exchange-rate) |
| 48 | extra-cargo (mod cargo exchange-rate) |
| 49 | extra-resources (assoc (->> cheapest-prod |
| 50 | (filter (comp neg? second)) |
| 51 | (map (fn [[chem mole]] |
| 52 | [chem (* -1 base-times mole)])) |
| 53 | (into {})) consuming extra-cargo) |
| 54 | rewrite-with (into #{} (keys extra-resources)) |
| 55 | second-chance (reduce-reaction graph producing rewrite-with) |
| 56 | recursive-times (map (fn [[chem ct]] |
| 57 | (let [er (- (get-in second-chance [producing 0 chem]))] |
| 58 | (println chem ct er) |
| 59 | (quot ct er))) |
| 60 | extra-resources)] |
| 61 | recursive-times)) |
| 62 | |
| 63 | (defn maximize-output [graph producing consuming cargo] |
| 64 | (produce-with (reduce-reaction graph producing consuming) |
| 65 | producing consuming cargo)) |
| 66 | |
| 67 | (defn day14 [] |
| 68 | (let [graphed (make-graph (get-list-from-file (input-file)))] |
| 69 | (part1 (find-lowest-exchange-rate graphed "FUEL" "ORE")) |
| 70 | (part2 (maximize-output graphed "FUEL" "ORE" 1000000000000)))) |