Add extremely broken day14pt2
[adventofcode2019.git] / src / adventofcode2019 / day14.clj
index e0e9b26402f7ae9ad1fa8153341bb20151409efa..8310b5eace0ea3e0188d37a99df694ca679045c5 100644 (file)
@@ -1,10 +1,7 @@
 (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))))