| 1 | (ns adventofcode2019.day14 |
| 2 | [:require [adventofcode2019.lib :refer :all] |
| 3 | [adventofcode2019.intcode :as i] |
| 4 | [clojure.string :as str] |
| 5 | [clojure.set :as set] |
| 6 | [clojure.core.match :refer [match]] |
| 7 | [clojure.math.combinatorics :as combo]]) |
| 8 | |
| 9 | (defn parse-reaction [reaction-text] |
| 10 | (let [parse-chemical (fn [text] |
| 11 | (let [[ct chem] (str/split (str/trim text) #" ")] |
| 12 | {chem (parse-int ct)})) |
| 13 | [inputs output] (str/split reaction-text #"=>") |
| 14 | [[out-chem out-ct]] (seq (parse-chemical output))] |
| 15 | {out-chem {(reduce merge {} (map parse-chemical (str/split inputs #","))) out-ct}})) |
| 16 | |
| 17 | (defn normalize-reaction [reaction] |
| 18 | (let [[output] (keys reaction) |
| 19 | arrows (reaction output) |
| 20 | inputs (keys arrows) |
| 21 | normalize-arrow (fn [[akey aval]] |
| 22 | {(reduce-kv (fn [m k v] |
| 23 | (assoc m k (rationalize (/ v aval)))) |
| 24 | {} akey) 1})] |
| 25 | {output (reduce merge {} (map normalize-arrow arrows))})) |
| 26 | |
| 27 | (defn make-graph [input] |
| 28 | (reduce (partial merge-with merge) |
| 29 | (map (comp normalize-reaction parse-reaction) input))) |
| 30 | |
| 31 | (defn find-lowest-exchange-rate [graph start end] |
| 32 | (let [reactions (graph start) |
| 33 | input-lists (keys reactions) |
| 34 | input-chems (mapv keys input-lists) |
| 35 | trade (fn [recv exch] |
| 36 | (let [rx (if (ratio? exch) (numerator exch) exch) |
| 37 | xc (if (ratio? exch) (denominator exch) 1) |
| 38 | units (int (Math/ceil (/ recv xc)))] |
| 39 | (* units rx))) |
| 40 | find-terminal #(match [%] |
| 41 | [({end v} :only [end])] v |
| 42 | :else nil) |
| 43 | calculate-er (fn [[chem ct]] |
| 44 | (trade ct (find-lowest-exchange-rate graph chem end))) |
| 45 | reaction-er #(reduce + (map calculate-er %))] |
| 46 | (if (some #{[end]} input-chems) |
| 47 | (->> input-lists |
| 48 | (map find-terminal) |
| 49 | (remove nil?) |
| 50 | (reduce min)) |
| 51 | (->> input-lists |
| 52 | (map reaction-er) |
| 53 | (reduce min))))) |
| 54 | |
| 55 | (defn day14 [] |
| 56 | (let [graphed (make-graph (get-list-from-file (input-file)))] |
| 57 | (part1 (find-lowest-exchange-rate graphed "FUEL" "ORE")) |
| 58 | #_(part2))) |