From 9c8f23161a5211f2a85063991514325f94d08852 Mon Sep 17 00:00:00 2001 From: Chris Alge Date: Mon, 13 Mar 2023 17:25:10 +0100 Subject: [PATCH] 2019 day 14 cleanup: introduced a proper data type for amount-chemical pairs; removed debug instructions; inserted the correct result in the challenge test --- 2019/day14_space_stoichiometry/src/lib.rs | 54 ++++++++++++----------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/2019/day14_space_stoichiometry/src/lib.rs b/2019/day14_space_stoichiometry/src/lib.rs index b7ae28d..1b195e2 100644 --- a/2019/day14_space_stoichiometry/src/lib.rs +++ b/2019/day14_space_stoichiometry/src/lib.rs @@ -2,9 +2,14 @@ use std::collections::{HashMap, VecDeque}; type Chemical = usize; +struct Reagent { + id: usize, + amount: usize, +} + struct Reaction { - input: Vec<(usize, Chemical)>, - output: (usize, Chemical), + input: Vec, + output: Reagent, } impl Reaction { @@ -22,9 +27,12 @@ impl Reaction { assert_eq!(in_components.len()%3, 0); let out_components: Vec<_> = out_str.split(' ').collect(); assert_eq!(out_components.len(), 2); - let output = (out_components[0].parse().unwrap(), get_chemical(out_components[1])); + let output = Reagent { + id: get_chemical(out_components[1]), + amount: out_components[0].parse().unwrap(), + }; - let input = in_components.chunks(3).map(|c| (c[0].parse::().unwrap(), get_chemical(c[1]))).collect(); + let input = in_components.chunks(3).map(|c| Reagent { id: get_chemical(c[1]), amount: c[0].parse::().unwrap(), }).collect(); Self { input, @@ -40,7 +48,7 @@ pub fn run(input: &str) -> (usize, usize) { let ore = chemicals.iter().position(|chem| chem == &String::from("ORE")).unwrap(); // dbg!(&chemicals); let first = break_down(&reactions, fuel, ore, 1); - let second = bisection_find(1000000000000/first, 10000000000000/first, &reactions, fuel, ore, 1000000000000); + let second = bisection_find(1_000_000_000_000/first, 10_000_000_000_000/first, &reactions, fuel, ore, 1_000_000_000_000); (first, second) } @@ -58,39 +66,35 @@ fn bisection_find(lower: usize, upper: usize, reactions: &[Reaction], target: us } fn break_down(reactions: &[Reaction], target: Chemical, raw: Chemical, amount: usize) -> usize { - let mut current = VecDeque::from([(amount, target)]); + let mut current = VecDeque::from([Reagent {amount, id: target, }]); let mut leftovers = HashMap::new(); - while !(current.len() == 1 && current[0].1 == raw) { - let (next_count, next_chem): (usize, Chemical) = current.pop_front().unwrap(); - if next_chem == raw { - current.push_back((next_count, next_chem)); + while !(current.len() == 1 && current[0].id == raw) { + let next = current.pop_front().unwrap(); + if next.id == raw { + current.push_back(next); continue; } - // dbg!(next_chem); - let reaction = reactions.iter().find(|r| r.output.1 == next_chem).unwrap(); - let multiplier = (next_count + reaction.output.0 - 1)/reaction.output.0; - *leftovers.entry(next_chem).or_insert(0) += (reaction.output.0 * multiplier).saturating_sub(next_count); - // eprintln!("Breaking down {next_count} {next_chem} into"); - for (input_count, input_chem) in &reaction.input { - let mut required = input_count * multiplier; - // eprintln!(" {required} {input_chem}"); - if let Some(left) = leftovers.get_mut(input_chem) { + let reaction = reactions.iter().find(|r| r.output.id == next.id).unwrap(); + let multiplier = (next.amount + reaction.output.amount - 1)/reaction.output.amount; + *leftovers.entry(next.id).or_insert(0) += (reaction.output.amount * multiplier).saturating_sub(next.amount); + for input in &reaction.input { + let mut required = input.amount * multiplier; + if let Some(left) = leftovers.get_mut(&input.id) { let consumed = required.min(*left); required -= consumed; *left -= consumed; - // eprintln!(" {required} after consuming leftovers. {left} left"); } if required > 0 { - if let Some(idx) = current.iter().position(|c| c.1 == *input_chem) { - current[idx].0 += required; + if let Some(idx) = current.iter().position(|c| c.id == input.id) { + current[idx].amount += required; } else { - current.push_back((required, *input_chem)); + current.push_back(Reagent { id: input.id, amount: required, }); } } } } - current[0].0 + current[0].amount } #[cfg(test)] @@ -111,6 +115,6 @@ mod tests { #[test] fn test_challenge() { let challenge_input = read_file("tests/challenge_input"); - assert_eq!(run(&challenge_input), (1582325, 0)); + assert_eq!(run(&challenge_input), (1582325, 2267486)); } }