(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]])
+ [:require [adventofcode2019.lib :refer :all]
+ [clojure.string :as str]
+ [clojure.core.match :refer [match]]])
(defn parse-reaction [reaction-text]
(let [parse-chemical (fn [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))}))
+ {out-chem [(reduce merge {} (map parse-chemical (str/split inputs #","))) out-ct]}))
(defn make-graph [input]
(reduce (partial merge-with merge)
- (map (comp normalize-reaction parse-reaction) input)))
+ (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 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 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)))
+ (part2 (maximize-output graphed "FUEL" "ORE" 1000000000000))))