From 85e033f369571a2a4d84be56266df84dcdda556c Mon Sep 17 00:00:00 2001 From: Wesley Moore Date: Sun, 22 Dec 2019 15:12:47 +1100 Subject: [PATCH] Day 14 part 1 --- 2019/input/day14.txt | 63 ++++++++++++++++++++++++++++ 2019/src/bin/day14.rs | 97 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 2019/input/day14.txt create mode 100644 2019/src/bin/day14.rs diff --git a/2019/input/day14.txt b/2019/input/day14.txt new file mode 100644 index 0000000..481d206 --- /dev/null +++ b/2019/input/day14.txt @@ -0,0 +1,63 @@ +10 KVPH => 5 HPRK +5 RSTBJ => 5 QKBQL +2 GZWFN, 21 WBPFQ => 5 KMFWH +5 JDJB, 1 FSWFT, 1 NKVSV => 6 MGKSL +5 BCRHK => 9 KXFTL +23 NKVSV, 2 RSTBJ => 9 QPBVD +19 BKFVS, 7 JZBFT => 7 XWTQ +14 JLXP, 4 LSCL => 8 FWLTD +173 ORE => 5 TZSDV +2 FPVH, 1 JDJB, 3 KHRW => 2 QLNJ +1 HTGMX, 1 GVJVK, 2 RLRK => 2 HWBM +1 GLVHT, 1 PBCT, 5 ZWKGV, 1 QSVJ, 2 FWLTD, 3 CNVPB, 1 QGNL => 8 RNLTX +1 KXZTS => 2 BKFVS +1 KVPH, 6 PVHPV, 2 TZSDV => 4 RLRK +118 ORE => 1 VRVZ +7 MGKSL, 4 HWBM => 2 GZWFN +5 PVHPV => 7 HTGMX +25 LSCL, 12 GVMFW => 6 ZWKGV +1 CTPND, 1 KXZTS => 3 FRQH +1 KXFTL => 3 PBCT +1 CMPX => 4 KZNBL +2 HDQVB, 1 QPBVD => 5 CTPND +14 KVPH => 1 FCBQN +3 XWTQ, 22 CTHM, 4 KVPH, 4 BZTV, 1 KMFWH, 12 NRFK => 7 CXVR +1 GVJVK => 7 RSTBJ +1 GVJVK => 4 NSQHW +3 NKVSV => 8 KHRW +8 HDQVB, 9 BCRHK => 6 GVMFW +142 ORE => 7 KVPH +4 TZSDV => 2 GVJVK +4 KVPH, 10 HWBM => 3 NRFK +47 PBCT, 15 CXVR, 45 GVJVK, 23 KZNBL, 1 WFPNP, 14 RNLTX => 1 FUEL +1 PCBNG => 4 QLJXM +1 SHTQF => 2 FNWBZ +2 FCBQN, 1 BCRHK => 5 HVFBV +1 BZTQ => 9 CTHM +16 SHTQF => 3 BZTQ +11 PBCT, 5 PCBNG, 2 CTPND => 1 WBPFQ +3 KHRW => 4 FSWFT +12 HDQVB, 1 PBCT, 9 NRFK => 9 VLWJL +5 SHTQF, 8 HVFBV => 6 BZTV +2 KZNBL, 7 NRFK => 3 DVFS +18 HTLSF, 14 DVFS => 6 TLFNL +1 RSTBJ => 1 NKVSV +2 QLNJ, 7 BZTQ => 6 PCBNG +1 HTLSF, 19 CMPX => 7 JDJB +6 KZNBL, 3 QSVJ => 8 SHTQF +3 HTLSF, 1 VRVZ => 6 CMPX +1 MGKSL, 15 CTPND => 6 STNPH +2 NKVSV, 7 JDJB => 4 KXZTS +3 KVPH => 4 QSVJ +1 HPRK, 9 PCBNG, 2 KXFTL => 9 CNVPB +27 GZWFN, 1 VLWJL, 15 LSCL => 3 GLVHT +162 ORE => 4 HTLSF +193 ORE => 8 PVHPV +9 TLFNL, 1 KHRW => 6 HDQVB +6 QLJXM, 4 FCBQN => 7 JLXP +3 HTLSF, 21 NSQHW, 18 GVJVK => 7 BCRHK +1 HTGMX, 20 CMPX, 6 RSTBJ => 6 FPVH +4 KXZTS, 7 CNVPB, 1 STNPH => 2 LSCL +3 KXZTS, 1 PCBNG => 3 JZBFT +22 WBPFQ, 22 FRQH, 1 QLNJ, 4 CTHM, 3 GVMFW, 1 KMFWH, 4 QKBQL => 4 WFPNP +3 QLJXM, 11 FNWBZ, 3 WBPFQ => 5 QGNL diff --git a/2019/src/bin/day14.rs b/2019/src/bin/day14.rs new file mode 100644 index 0000000..d804001 --- /dev/null +++ b/2019/src/bin/day14.rs @@ -0,0 +1,97 @@ +use std::collections::HashMap; +use std::{fs, io}; + +#[derive(Debug)] +struct Material<'a> { + name: &'a str, + amount: usize, +} + +#[derive(Debug)] +struct Reaction<'a> { + inputs: Vec>, + output: Material<'a>, +} + +fn main() -> io::Result<()> { + let input = fs::read_to_string("input/day14.txt")?; + let reactions = parse_input(&input); + + println!("Day 1 part 1: {}", ore_required(&reactions)); + + Ok(()) +} + +fn parse_input(input: &str) -> Vec { + input + .lines() + .map(|line| { + let mut io = line.trim().split(" => "); + let input = io.next().unwrap(); + let output = io.next().map(parse_material).unwrap(); + let inputs = input.split(", ").map(parse_material).collect(); + + Reaction { inputs, output } + }) + .collect() +} + +fn parse_material(s: &str) -> Material { + let mut parts = s.split_whitespace(); + Material { + amount: parts.next().and_then(|amount| amount.parse().ok()).unwrap(), + name: parts.next().unwrap(), + } +} + +fn ore_required(reactions: &[Reaction]) -> usize { + // Find FUEL and work back to ORE to find paths? + let map = reactions + .iter() + .map(|reaction| (reaction.output.name, reaction)) + .collect::>(); + + let mut inventory = HashMap::new(); + run_reaction("FUEL", &map, &mut inventory); + inventory.get("ORE").copied().unwrap_or_default().abs() as usize +} + +// Run the named reaction, updating the inventory +fn run_reaction<'a>( + name: &'a str, + tree: &'a HashMap<&'a str, &'a Reaction>, + inventory: &mut HashMap<&'a str, isize>, +) { + let node = tree[name]; + node.inputs.iter().for_each(|input| { + if input.name == "ORE" { + *inventory.entry("ORE").or_default() -= input.amount as isize; + } else { + *inventory.entry(input.name).or_default() -= input.amount as isize; + while inventory.get(input.name).copied().unwrap_or_default() < 0 { + run_reaction(input.name, tree, inventory); + } + } + }); + *inventory.entry(name).or_default() += node.output.amount as isize; +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_small_example() { + let input = "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 +"; + let reactions = parse_input(&input); + + assert_eq!(ore_required(&reactions), 165); + } +}