From 83dce003d869eab6a8edf5e17c337c0f631431b2 Mon Sep 17 00:00:00 2001 From: Johannes Date: Sat, 14 Dec 2019 21:29:36 +0100 Subject: [PATCH] day 14 task 1 --- input/day14.txt | 54 +++++++++++++++++++++++++++++ src/main.rs | 2 +- src/tasks/day14.rs | 84 ++++++++++++++++++++++++++++++++++++++++++++++ src/tasks/mod.rs | 1 + 4 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 input/day14.txt create mode 100644 src/tasks/day14.rs diff --git a/input/day14.txt b/input/day14.txt new file mode 100644 index 0000000..32ca5df --- /dev/null +++ b/input/day14.txt @@ -0,0 +1,54 @@ +156 ORE => 6 TLFQZ +1 SZFV => 5 TNXGD +1 BQLJ, 3 VNKPF => 8 BQXZ +43 FPRFS, 5 CQJT, 20 LDKTQ, 48 ZPBLH, 21 MFVG, 43 WLWZQ, 1 ZWZQ, 11 PQZJP, 56 CTJGD, 35 SGDVW => 1 FUEL +11 BQXZ, 1 PRCSN => 7 DVFD +7 VWXB, 2 PRCSN, 24 VJSR, 9 MDWCG, 4 MFVG => 4 ZWZQ +32 BQXZ, 5 XDSHP, 16 KTXJR, 7 VJSR, 3 MDWCG, 11 KZFZG, 3 NVBN => 5 ZPBLH +2 BQLJ, 2 RSKH, 3 VWXB => 2 GWXCF +6 PRCSN, 1 NCRZ => 8 VJSR +5 TMQLD => 9 VDQL +9 MZQZS, 1 FLRB => 5 BQLJ +4 KLHS => 5 PQZJP +1 WJTS, 1 NCRZ, 27 XDSHP => 8 MFVG +1 FNXMV, 30 FPKM => 8 RDMDL +1 TNXGD, 21 XBCLW, 5 CWNV => 3 RSKH +4 KQFPJ => 2 NCRZ +10 CWNV, 8 HSXW => 9 FNXMV +2 TNXGD, 4 CWNV, 13 VJSR => 8 KTXJR +3 NCRZ, 1 GWXCF, 8 NVBN, 6 MDWCG, 3 VWXB, 4 KTXJR, 4 DVFD, 3 QXCV => 9 FPRFS +5 MZQZS, 9 TBVRN => 7 SZFV +37 GWXCF, 15 RDMDL, 2 MDWCG => 7 CQJT +1 VDQL, 2 HSXW => 4 NVBN +18 QHMTL, 7 FLRB, 1 SZFV => 3 FPKM +6 VDQL => 1 FNCN +3 QPHT => 7 LDKTQ +1 TLFQZ => 8 FWFR +7 VDQL, 8 KZFZG => 3 HSXW +9 TBVRN => 7 MZQZS +1 FLRB, 44 VNKPF, 1 LVZF => 8 QXCV +1 WLWZQ, 3 TBVRN, 4 TLFQZ => 9 KQFPJ +1 BQLJ, 1 PRCSN, 8 DHTNG => 5 VWXB +1 XDSHP, 6 NVBN => 1 BDGC +8 PRCSN, 1 DHTNG => 2 WJTS +19 DHTNG, 22 WLWZQ => 9 LVZF +185 ORE => 7 WLWZQ +1 TMQLD, 1 MZQZS => 8 KZFZG +111 ORE => 4 TBVRN +31 VDQL, 14 MZQZS => 7 XBCLW +6 VDQL, 3 KVPK => 9 SGDVW +1 FNCN => 6 QMKT +1 FNCN, 3 TMQLD => 7 VNKPF +2 QPHT => 6 VQXCJ +2 LDKTQ, 3 VQXCJ => 5 FLRB +1 FNCN, 3 FPKM, 1 SZFV => 2 DHTNG +1 KZFZG => 9 QHMTL +141 ORE => 5 QPHT +16 TNXGD => 9 CWNV +1 KQFPJ, 29 FWFR => 2 KVPK +1 TNXGD, 7 KLHS => 2 XDSHP +7 WJTS => 6 MDWCG +3 BDGC, 3 XDSHP, 1 NCRZ => 4 CTJGD +3 QMKT => 6 PRCSN +24 FWFR => 2 TMQLD +8 VNKPF => 3 KLHS \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index ae267c2..6415156 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ mod tasks; fn main() { - tasks::day13::run(); + tasks::day14::run(); } diff --git a/src/tasks/day14.rs b/src/tasks/day14.rs new file mode 100644 index 0000000..af0d8cd --- /dev/null +++ b/src/tasks/day14.rs @@ -0,0 +1,84 @@ +use itertools::Itertools; +use std::collections::HashMap; + +pub fn run() { + fn parser(s: &str) -> Chemical { + let (n, t) = s.split(" ").collect_tuple().unwrap(); + Chemical(n.parse().unwrap(), t) + } + let text = std::fs::read_to_string("input/day14.txt").unwrap(); + // maps from a chemical to the chemicals required to create it + let rules: HashMap<_, _> = text + .lines() + .map(|line| { + let (left, right) = line + .split("=>") + .map(|it| it.trim()) + .collect_tuple() + .unwrap(); + ( + parser(right).1, + ( + parser(right).0, + left.split(",").map(|it| parser(it.trim())).collect_vec(), + ), + ) + }) + .collect(); + /* + The idea is: the rules create a DAG of requirements. + We store for every chemical a list of the chemicals that rely on it. + We create a mapping from the chemicals to the amount of the chemicals needed + by its already processed ancestors in the rule DAG. + Then we process all chemicals C, starting with "FUEL", of which all ancestors are already + processed. That means, that our mapping of the amounts stores the correct sum of what is + needed of the chemical (we round that up, so it matches the amount given on the right + hand rule side). We then calculate, using the rules, how much of other chemicals C' we need + to produce the desired amount. We add up the amount of the required children C' in + `requirements`. We then remove C from the chem_used_by list of C'. + Once a chemical has an empty used_by list it is ready for processing. + */ + + // maps for every chemical to the ones using it + let mut chem_used_by: HashMap<&str, Vec<&str>> = + rules + .iter() + .fold(HashMap::new(), |mut map, (result, (_, ingredients))| { + ingredients.iter().for_each(|Chemical(_, ingredient)| { + map.entry(&ingredient).or_insert(vec![]).push(result) + }); + map + }); + chem_used_by.insert("FUEL", vec![]); + // the amount of a not processed chemical C, which is needed by the chemicals that rely on C + let mut requirements = HashMap::<&str, usize>::new(); + requirements.insert("FUEL", 1); + while let Some((name, amount)) = requirements + .iter() + .find(|(name, _)| chem_used_by[*name].is_empty() && **name != "ORE") + { + // needed to remove immutable borrow of `requirements` from above + let name = *name; + let amount = *amount; + let (reaction_size, req_vec) = &rules + .get(&name) + .expect(&format!("unknown chemical in rules: {}", name)); + let demand = if amount % reaction_size == 0 { + amount / reaction_size + } else { + amount / reaction_size + 1 + }; + for Chemical(req_amount, req_name) in req_vec { + chem_used_by + .get_mut(req_name) + .unwrap() + .retain(|x| *x != name); + *requirements.entry(req_name).or_insert(0) += demand * req_amount; + } + requirements.remove(name); + } + println!("Task 1: {} ORE is needed", requirements["ORE"]); +} + +#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)] +struct Chemical<'a>(usize, &'a str); diff --git a/src/tasks/mod.rs b/src/tasks/mod.rs index 921a848..544a5a1 100644 --- a/src/tasks/mod.rs +++ b/src/tasks/mod.rs @@ -10,3 +10,4 @@ pub mod day10; pub mod day11; pub mod day12; pub mod day13; +pub mod day14;