From: Jack Kinsey Date: Wed, 18 Dec 2019 23:01:58 +0000 (-0500) Subject: Add untested day14pt1 (but it has tests!) X-Git-Url: http://git.jkinsey.net/?p=adventofcode2019.git;a=commitdiff_plain;h=e26daef486624d7197207d38b601a4e505e6ef26 Add untested day14pt1 (but it has tests!) --- diff --git a/src/adventofcode2019/core.clj b/src/adventofcode2019/core.clj index ca8684b..3e6794e 100644 --- a/src/adventofcode2019/core.clj +++ b/src/adventofcode2019/core.clj @@ -1,7 +1,7 @@ (ns adventofcode2019.core [:require (adventofcode2019 day01 day02 day03 day04 day05 day06 day07 day08 day09 day10 - day11 day12 day13)]) + day11 day12 day13 day14)]) (defn -main ([] diff --git a/src/adventofcode2019/day14.clj b/src/adventofcode2019/day14.clj new file mode 100644 index 0000000..e0e9b26 --- /dev/null +++ b/src/adventofcode2019/day14.clj @@ -0,0 +1,58 @@ +(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))) diff --git a/test/adventofcode2019/day14_test.clj b/test/adventofcode2019/day14_test.clj new file mode 100644 index 0000000..1a6bd86 --- /dev/null +++ b/test/adventofcode2019/day14_test.clj @@ -0,0 +1,37 @@ +(ns adventofcode2019.day14-test + (:require [clojure.test :refer :all] + [adventofcode2019.day14 :refer :all])) + +(deftest check-make-graph + (is (= (make-graph ["3 ORE => 2 ABC" + "3 ABC => 1 FUEL"]) + {"ABC" {{"ORE" 3/2} 1} + "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 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"))))