(ns adventofcode2019.day14 [:require [adventofcode2019.lib :refer :all] [adventofcode2019.intcode :as i] [clojure.string :as str] [clojure.set :as set] [clojure.core.match :refer [match]] [clojure.math.combinatorics :as combo]]) (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 normalize-reaction [reaction] (let [[output] (keys reaction) arrows (reaction output) inputs (keys arrows) normalize-arrow (fn [[akey aval]] {(reduce-kv (fn [m k v] (assoc m k (rationalize (/ v aval)))) {} akey) 1})] {output (reduce merge {} (map normalize-arrow arrows))})) (defn make-graph [input] (reduce (partial merge-with merge) (map (comp normalize-reaction parse-reaction) input))) (defn find-lowest-exchange-rate [graph start end] (let [reactions (graph start) input-lists (keys reactions) input-chems (mapv keys input-lists) trade (fn [recv exch] (let [rx (if (ratio? exch) (numerator exch) exch) xc (if (ratio? exch) (denominator exch) 1) units (int (Math/ceil (/ recv xc)))] (* units rx))) find-terminal #(match [%] [({end v} :only [end])] v :else nil) calculate-er (fn [[chem ct]] (trade ct (find-lowest-exchange-rate graph chem end))) reaction-er #(reduce + (map calculate-er %))] (if (some #{[end]} input-chems) (->> input-lists (map find-terminal) (remove nil?) (reduce min)) (->> input-lists (map reaction-er) (reduce min))))) (defn day14 [] (let [graphed (make-graph (get-list-from-file (input-file)))] (part1 (find-lowest-exchange-rate graphed "FUEL" "ORE")) #_(part2)))