Add untested day14pt1 (but it has tests!)
[adventofcode2019.git] / src / adventofcode2019 / day14.clj
CommitLineData
e26daef4
JK
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)))