Rework day14pt1
authorJack Kinsey <kinsey_john@bah.com>
Thu, 19 Dec 2019 17:12:42 +0000 (12:12 -0500)
committerJack Kinsey <kinsey_john@bah.com>
Thu, 19 Dec 2019 17:30:49 +0000 (12:30 -0500)
day14pt1 was tested failing, so it's been reworked. Local tests are
green, but this version hasn't been checked against AoC.

Also, beef up local testing.

src/adventofcode2019/day14.clj
src/adventofcode2019/lib.clj
test/adventofcode2019/core_test.clj
test/adventofcode2019/day14_test.clj
test/adventofcode2019/template_test.clj [new file with mode: 0644]

index e0e9b26402f7ae9ad1fa8153341bb20151409efa..e2aae3e11000ebd9e14f8920caec7d10234c9fea 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 [[inputs moles] (graph producing)
+        in-chems (keys inputs)
+        replace-term (fn [chem]
+                       (if (or (= chem consuming)
+                               (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= ch consuming) (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 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 find-lowest-exchange-rate [graph producing consuming]
+  (get-in (reduce-reaction graph producing consuming)
+          [producing 0 consuming]))
 
 (defn day14 []
   (let [graphed (make-graph (get-list-from-file (input-file)))]
index 890ddf5b8cef7ca064c5608f61736a675aaee8e0..4b424a8fd47f53a92091bc29f635af1f7ee0ecc2 100644 (file)
@@ -24,6 +24,9 @@
   (+ (Math/abs (- ax bx))
      (Math/abs (- ay by))))
 
+(defn mmap [f m]
+  (reduce-kv #(assoc %1 %2 (f %3)) {} m))
+
 (def part1 
   #(println (str "Part 1: " %)))
 (def part2 
index d571560a4ffda7f4cbb0741cb7fa364fc0729965..1b5e647f49c665c197c44f1457c51b198f5ae3cc 100644 (file)
@@ -1,7 +1,3 @@
 (ns adventofcode2019.core-test
   (:require [clojure.test :refer :all]
             [adventofcode2019.core :refer :all]))
-
-(deftest a-test
-  (testing "FIXME, I fail."
-    (is (= 0 1))))
index 1a6bd86b138a7fd01bb0949b17f3ec88a2781b44..7e99dcc401bbcd131861ed0ca6a6704ae8ceb18e 100644 (file)
@@ -2,36 +2,86 @@
   (:require [clojure.test :refer :all]
             [adventofcode2019.day14 :refer :all]))
 
-(deftest check-make-graph
-  (is (= (make-graph ["3 ORE => 2 ABC" 
+(deftest test-make-graph
+  (is (= (make-graph ["3 ORE => 2 ABC"
                       "3 ABC => 1 FUEL"])
-         {"ABC"  {{"ORE" 3/2} 1}
-          "FUEL" {{"ABC" 3}   1}})))
+         {"ABC"  [{"ORE" 3} 2]
+          "FUEL" [{"ABC" 3} 1]})))
 
-(deftest simple-exchange
-  (is (= 3 (find-lowest-exchange-rate {"FUEL" {{"ORE" 1, "ABC" 2, "DEF" 3} 1 
-                                               {"ORE" 3} 1 
-                                               {"GHI" 5/2} 1}} 
-                                      "FUEL" "ORE"))))
+(deftest test-reduce
+  (is (= (reduce-reaction (make-graph ["9 ORE => 2 A"
+                                       "8 ORE => 3 B"
+                                       "7 ORE => 5 C"
+                                       "3 A, 4 B => 1 AB"
+                                       "5 B, 7 C => 1 BC"
+                                       "4 C, 1 A => 1 CA"
+                                       "2 AB, 3 BC, 4 CA => 1 FUEL"])
+                          "FUEL", "ORE")
+         {"A" [{"ORE" 9} 2]
+          "B" [{"ORE" 8} 3]
+          "C" [{"ORE" 7} 5]
+          "AB" [{"A" 3, "B" 4} 1]
+          "BC" [{"B" 5, "C" 7} 1]
+          "CA" [{"C" 4, "A" 1} 1]
+          "FUEL" [{"ORE" 165, "A" 0
+                   "B" -1, "AB" 0
+                   "C" -3, "BC" 0
+                   "CA" 0} 1]})))
 
-(deftest trading-up
-  (is (= 6 (find-lowest-exchange-rate (make-graph ["3 ORE => 2 ABC"
-                                                   "3 ABC => 1 FUEL"])
-                                      "FUEL" "ORE"))))
-
-(deftest complicated-exchange
-  (is (= 2 (find-lowest-exchange-rate (make-graph ["3 ORE => 2 ABC"
-                                                   "3 ABC => 1 FUEL"
-                                                   "2 ORE => 1 CDE"
-                                                   "1 CDE => 1 FUEL"])
-                                      "FUEL" "ORE"))))
-
-(deftest very-tricky-exchange
-  (is (= 3 (find-lowest-exchange-rate (make-graph ["3 ORE => 2 ABC"
-                                                   "3 ABC => 1 FUEL"
-                                                   "4 ORE => 1 CDE"
-                                                   "1 CDE => 1 FUEL"
-                                                   "3 ORE => 2 FGH"
-                                                   "1 FGH => 1 IJK"
-                                                   "1 IJK => 1 FUEL"])
-                                      "FUEL" "ORE"))))
+(deftest examples
+  (is (= 31 (find-lowest-exchange-rate (make-graph ["10 ORE => 10 A"
+                                                    "1 ORE => 1 B"
+                                                    "7 A, 1 B => 1 C"
+                                                    "7 A, 1 C => 1 D"
+                                                    "7 A, 1 D => 1 E"
+                                                    "7 A, 1 E => 1 FUEL"])
+                                       "FUEL", "ORE")))
+  (is (= 165 (find-lowest-exchange-rate (make-graph ["9 ORE => 2 A"
+                                                     "8 ORE => 3 B"
+                                                     "7 ORE => 5 C"
+                                                     "3 A, 4 B => 1 AB"
+                                                     "5 B, 7 C => 1 BC"
+                                                     "4 C, 1 A => 1 CA"
+                                                     "2 AB, 3 BC, 4 CA => 1 FUEL"])
+                                        "FUEL", "ORE")))
+  (is (= 13312 (find-lowest-exchange-rate (make-graph ["157 ORE => 5 NZVS"
+                                                       "165 ORE => 6 DCFZ"
+                                                       "44 XJWVT, 5 KHKGT, 1 QDVJ, 29 NZVS, 9 GPVTF, 48 HKGWZ => 1 FUEL"
+                                                       "12 HKGWZ, 1 GPVTF, 8 PSHF => 9 QDVJ"
+                                                       "179 ORE => 7 PSHF"
+                                                       "177 ORE => 5 HKGWZ"
+                                                       "7 DCFZ, 7 PSHF => 2 XJWVT"
+                                                       "165 ORE => 2 GPVTF"
+                                                       "3 DCFZ, 7 NZVS, 5 HKGWZ, 10 PSHF => 8 KHKGT"])
+                                          "FUEL", "ORE")))
+  (is (= 180697 (find-lowest-exchange-rate (make-graph ["2 VPVL, 7 FWMGM, 2 CXFTF, 11 MNCFX => 1 STKFG"
+                                                        "17 NVRVD, 3 JNWZP => 8 VPVL"
+                                                        "53 STKFG, 6 MNCFX, 46 VJHF, 81 HVMC, 68 CXFTF, 25 GNMV => 1 FUEL"
+                                                        "22 VJHF, 37 MNCFX => 5 FWMGM"
+                                                        "139 ORE => 4 NVRVD"
+                                                        "144 ORE => 7 JNWZP"
+                                                        "5 MNCFX, 7 RFSQX, 2 FWMGM, 2 VPVL, 19 CXFTF => 3 HVMC"
+                                                        "5 VJHF, 7 MNCFX, 9 VPVL, 37 CXFTF => 6 GNMV"
+                                                        "145 ORE => 6 MNCFX"
+                                                        "1 NVRVD => 8 CXFTF"
+                                                        "1 VJHF, 6 MNCFX => 4 RFSQX"
+                                                        "176 ORE => 6 VJHF"])
+                                           "FUEL", "ORE")))
+  (is (= 2210736 (find-lowest-exchange-rate (make-graph ["171 ORE => 8 CNZTR"
+                                                         "7 ZLQW, 3 BMBT, 9 XCVML, 26 XMNCP, 1 WPTQ, 2 MZWV, 1 RJRHP => 4 PLWSL"
+                                                         "114 ORE => 4 BHXH"
+                                                         "14 VRPVC => 6 BMBT"
+                                                         "6 BHXH, 18 KTJDG, 12 WPTQ, 7 PLWSL, 31 FHTLT, 37 ZDVW => 1 FUEL"
+                                                         "6 WPTQ, 2 BMBT, 8 ZLQW, 18 KTJDG, 1 XMNCP, 6 MZWV, 1 RJRHP => 6 FHTLT"
+                                                         "15 XDBXC, 2 LTCX, 1 VRPVC => 6 ZLQW"
+                                                         "13 WPTQ, 10 LTCX, 3 RJRHP, 14 XMNCP, 2 MZWV, 1 ZLQW => 1 ZDVW"
+                                                         "5 BMBT => 4 WPTQ"
+                                                         "189 ORE => 9 KTJDG"
+                                                         "1 MZWV, 17 XDBXC, 3 XCVML => 2 XMNCP"
+                                                         "12 VRPVC, 27 CNZTR => 2 XDBXC"
+                                                         "15 KTJDG, 12 BHXH => 5 XCVML"
+                                                         "3 BHXH, 2 VRPVC => 7 MZWV"
+                                                         "121 ORE => 7 VRPVC"
+                                                         "7 XCVML => 6 RJRHP"
+                                                         "5 BHXH, 4 VRPVC => 5 LTCX"])
+                                            "FUEL", "ORE"))))
diff --git a/test/adventofcode2019/template_test.clj b/test/adventofcode2019/template_test.clj
new file mode 100644 (file)
index 0000000..bf3ebec
--- /dev/null
@@ -0,0 +1,6 @@
+(ns adventofcode2019.day00-test
+  (:require [clojure.test :refer :all]
+            [adventofcode2019.day00 :refer :all]))
+
+(deftest examples
+  (is (= 0 1)))