Completed day 14 part 1
This commit is contained in:
parent
f8e836f780
commit
9667e214b9
59
day14/Cargo.lock
generated
Normal file
59
day14/Cargo.lock
generated
Normal file
@ -0,0 +1,59 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "day14"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[metadata]
|
||||
"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
|
||||
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
"checksum memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3197e20c7edb283f87c071ddfc7a2cca8f8e0b888c242959846a6fce03c72223"
|
||||
"checksum regex 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b5508c1941e4e7cb19965abef075d35a9a8b5cdf0846f30b4050e9b55dc55e87"
|
||||
"checksum regex-syntax 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e734e891f5b408a29efbf8309e656876276f49ab6a6ac208600b4419bd893d90"
|
||||
"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
|
11
day14/Cargo.toml
Normal file
11
day14/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "day14"
|
||||
version = "0.1.0"
|
||||
authors = ["Tyler Hallada <tyler@hallada.net>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
lazy_static = "1.4.0"
|
||||
regex = "1.3.3"
|
62
day14/input/input.txt
Normal file
62
day14/input/input.txt
Normal file
@ -0,0 +1,62 @@
|
||||
1 HJDM, 1 BMPDP, 8 DRCX, 2 TCTBL, 1 KGWDJ, 16 BRLF, 2 LWPB, 7 KDFQ => 6 ZSPL
|
||||
1 PVRCK, 3 RSLR, 4 JBZD => 6 LCHRC
|
||||
10 FCBVC, 1 TSJSJ, 20 SQCQ => 9 PNQLP
|
||||
1 MBVL => 6 TSZJ
|
||||
1 HWGQF => 4 ZSLVH
|
||||
1 TBDSC, 13 TSZJ => 1 HRZH
|
||||
1 RSLR, 1 LJWM => 3 RSFJR
|
||||
1 VMZFB => 2 MBVL
|
||||
4 DSTHJ, 2 TSZJ, 13 MBVL => 4 ZWLGK
|
||||
1 MKTZ, 18 RVFJB, 1 RSLR, 2 HRZH, 14 ZWLGK, 4 RJFTV => 1 ZCVL
|
||||
6 KDFQ, 1 PNQLP, 1 HRZH => 9 DLPMH
|
||||
1 DSVT, 22 DRCX, 18 RJFTV, 2 MKTZ, 13 FVZBX, 15 SLTNZ, 7 ZSLVH => 5 GWJC
|
||||
2 JZSJ, 3 ZSLVH, 6 HNRXC => 8 RJFTV
|
||||
1 TSZJ => 7 GFVG
|
||||
5 VMZFB => 4 JBZD
|
||||
1 PBFZ, 23 JBZD, 2 LJWM => 1 TSJSJ
|
||||
7 ZPQD => 7 VMZFB
|
||||
2 LCHRC => 8 PXHK
|
||||
2 TSZJ, 1 KCXMF, 1 FKJGC => 6 HWGQF
|
||||
4 PBFZ => 1 FCBVC
|
||||
1 GMWHM, 4 JQBKW => 8 SQCQ
|
||||
5 SHMP => 5 PVRCK
|
||||
10 KCXMF => 3 DRCX
|
||||
15 VMZFB, 2 RSFJR => 6 KDFQ
|
||||
35 HNRXC => 2 CJLG
|
||||
8 MKTZ, 1 FCBVC, 12 HJDM => 9 BRLF
|
||||
171 ORE => 8 GMWHM
|
||||
8 RVFJB, 3 CJLG, 9 SLTNZ => 3 LWPB
|
||||
1 PXHK, 2 RSFJR => 3 FVZBX
|
||||
1 CJLG, 1 HRZH, 10 MKTZ => 8 KGWDJ
|
||||
1 RSFJR => 3 FKJGC
|
||||
1 NXCZM, 31 FKJGC => 2 MKTZ
|
||||
18 XLWBP => 6 MBLWL
|
||||
22 HNRXC => 8 FTGK
|
||||
3 KGWDJ, 1 MLBJ, 5 HJDM => 7 DSVT
|
||||
9 KDFQ => 5 NXCZM
|
||||
2 RVFJB, 4 LGDKL, 1 PXHK => 5 CVTR
|
||||
1 RSFJR, 6 GMWHM, 20 TSJSJ => 9 LGDKL
|
||||
5 KCXMF => 9 RBDP
|
||||
6 GWJC, 16 ZCVL, 29 JZSJ, 1 ZSPL, 35 MBLWL, 30 BWFRH, 2 MSFDB, 13 BMPDP, 11 FTGK, 1 ZWLGK => 1 FUEL
|
||||
6 GFVG, 2 TVQP => 8 HJDM
|
||||
1 CJLG, 13 PBFZ => 6 JZSJ
|
||||
3 CVTR => 3 BMPDP
|
||||
16 FPKMV, 1 ZSLVH => 8 MSFDB
|
||||
9 JBZD, 12 LCHRC => 8 TBDSC
|
||||
133 ORE => 3 LJWM
|
||||
107 ORE => 7 SHMP
|
||||
1 KDFQ, 1 LJWM => 9 FPKMV
|
||||
3 PXHK => 4 BWFRH
|
||||
123 ORE => 4 JQBKW
|
||||
2 FVZBX, 1 JZSJ => 8 XLWBP
|
||||
117 ORE => 2 ZPQD
|
||||
7 NXCZM => 7 HNRXC
|
||||
1 MLBJ, 22 RSLR => 8 KCXMF
|
||||
2 TBDSC => 8 RVFJB
|
||||
1 KDFQ, 23 DSTHJ => 7 SLTNZ
|
||||
3 RSFJR => 6 MLBJ
|
||||
5 PVRCK, 2 SQCQ => 9 RSLR
|
||||
1 LGDKL, 17 MBVL, 6 PNQLP => 5 TVQP
|
||||
3 RBDP => 6 TCTBL
|
||||
1 DLPMH, 1 GFVG, 3 MBVL => 2 DSTHJ
|
||||
21 VMZFB, 2 LJWM => 1 PBFZ
|
6
day14/input/test1.txt
Normal file
6
day14/input/test1.txt
Normal file
@ -0,0 +1,6 @@
|
||||
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
|
7
day14/input/test2.txt
Normal file
7
day14/input/test2.txt
Normal file
@ -0,0 +1,7 @@
|
||||
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
|
9
day14/input/test3.txt
Normal file
9
day14/input/test3.txt
Normal file
@ -0,0 +1,9 @@
|
||||
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
|
12
day14/input/test4.txt
Normal file
12
day14/input/test4.txt
Normal file
@ -0,0 +1,12 @@
|
||||
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
|
17
day14/input/test5.txt
Normal file
17
day14/input/test5.txt
Normal file
@ -0,0 +1,17 @@
|
||||
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
|
298
day14/src/main.rs
Normal file
298
day14/src/main.rs
Normal file
@ -0,0 +1,298 @@
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::error::Error;
|
||||
use std::fs::read_to_string;
|
||||
use std::result;
|
||||
use std::str::FromStr;
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
type Result<T> = result::Result<T, Box<dyn Error>>;
|
||||
|
||||
const INPUT: &str = "input/input.txt";
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct Reactions {
|
||||
reactions: HashMap<String, Reaction>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct Reaction {
|
||||
output: ChemicalAmount,
|
||||
inputs: Vec<ChemicalAmount>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Hash, PartialEq, Eq)]
|
||||
struct ChemicalAmount {
|
||||
chemical: String,
|
||||
amount: u32,
|
||||
}
|
||||
|
||||
impl FromStr for Reactions {
|
||||
type Err = Box<dyn Error>;
|
||||
|
||||
fn from_str(s: &str) -> Result<Reactions> {
|
||||
lazy_static! {
|
||||
static ref SOURCE_CHEMICALS: Regex =
|
||||
Regex::new(concat!(r"(?P<input_amount>\d+) (?P<input_chemical>\w+),? ",)).unwrap();
|
||||
static ref OUTPUT_CHEMICAL: Regex = Regex::new(concat!(
|
||||
r"=> (?P<output_amount>\d+) (?P<output_chemical>\w+)"
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
let mut reactions = HashMap::new();
|
||||
for line in s.trim().split('\n') {
|
||||
let mut inputs: Vec<ChemicalAmount> = vec![];
|
||||
for captures in SOURCE_CHEMICALS.captures_iter(line) {
|
||||
inputs.push(ChemicalAmount {
|
||||
chemical: captures["input_chemical"].to_string(),
|
||||
amount: captures["input_amount"].parse()?,
|
||||
});
|
||||
}
|
||||
match OUTPUT_CHEMICAL.captures(line) {
|
||||
None => {
|
||||
return Err(From::from(
|
||||
"Malformed reactions, no output chemical could be found",
|
||||
));
|
||||
}
|
||||
Some(captures) => {
|
||||
let output = ChemicalAmount {
|
||||
chemical: captures["output_chemical"].to_string(),
|
||||
amount: captures["output_amount"].parse()?,
|
||||
};
|
||||
reactions.insert(output.chemical.clone(), Reaction { inputs, output });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Ok(Reactions { reactions })
|
||||
}
|
||||
}
|
||||
|
||||
impl Reactions {
|
||||
fn new() -> Reactions {
|
||||
Reactions {
|
||||
reactions: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn calculate_ore_required(
|
||||
reactions: &Reactions,
|
||||
produced_chemical: &ChemicalAmount,
|
||||
left_overs: &mut HashMap<String, u32>,
|
||||
) -> u32 {
|
||||
let reaction = &reactions.reactions[&produced_chemical.chemical];
|
||||
let mut needed_amount = produced_chemical.amount;
|
||||
let mut left_over = 0;
|
||||
if let Some(left_over_amount) = left_overs.get(&produced_chemical.chemical) {
|
||||
left_over = *left_over_amount;
|
||||
}
|
||||
|
||||
if left_over > 0 {
|
||||
if left_over >= needed_amount {
|
||||
left_overs.insert(
|
||||
produced_chemical.chemical.clone(),
|
||||
left_over - needed_amount,
|
||||
);
|
||||
return 0;
|
||||
} else {
|
||||
left_overs.insert(produced_chemical.chemical.clone(), 0);
|
||||
needed_amount -= left_over;
|
||||
}
|
||||
}
|
||||
|
||||
let ratio: f32 = needed_amount as f32 / reaction.output.amount as f32;
|
||||
let production_count = ratio.ceil() as u32;
|
||||
left_overs.insert(
|
||||
produced_chemical.chemical.clone(),
|
||||
(reaction.output.amount * production_count) - needed_amount,
|
||||
);
|
||||
|
||||
if reaction.inputs.len() == 1 && reaction.inputs[0].chemical == "ORE" {
|
||||
return reaction.inputs[0].amount * production_count;
|
||||
} else {
|
||||
return reaction
|
||||
.inputs
|
||||
.iter()
|
||||
.map(|input| {
|
||||
calculate_ore_required(
|
||||
reactions,
|
||||
&ChemicalAmount {
|
||||
chemical: input.chemical.clone(),
|
||||
amount: input.amount * production_count,
|
||||
},
|
||||
left_overs,
|
||||
)
|
||||
})
|
||||
.sum();
|
||||
}
|
||||
}
|
||||
|
||||
fn read_reactions(filename: &str) -> Result<Reactions> {
|
||||
let reactions = read_to_string(filename)?.parse()?;
|
||||
Ok(reactions)
|
||||
}
|
||||
|
||||
fn solve_part1(filename: &str) -> Result<u32> {
|
||||
let reactions = read_reactions(filename)?;
|
||||
let mut left_overs = HashMap::new();
|
||||
Ok(calculate_ore_required(
|
||||
&reactions,
|
||||
&ChemicalAmount {
|
||||
chemical: "FUEL".to_string(),
|
||||
amount: 1,
|
||||
},
|
||||
&mut left_overs,
|
||||
))
|
||||
}
|
||||
|
||||
fn solve_part2(filename: &str) -> Result<u64> {
|
||||
Ok(1)
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
println!("Part 1: {}", solve_part1(INPUT)?);
|
||||
println!("Part 2: {}", solve_part2(INPUT)?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
const TEST_INPUT1: &str = "input/test1.txt";
|
||||
const TEST_INPUT2: &str = "input/test2.txt";
|
||||
const TEST_INPUT3: &str = "input/test3.txt";
|
||||
const TEST_INPUT4: &str = "input/test4.txt";
|
||||
const TEST_INPUT5: &str = "input/test5.txt";
|
||||
|
||||
fn reactions_1() -> Reactions {
|
||||
Reactions {
|
||||
reactions: vec![
|
||||
(
|
||||
"E".to_string(),
|
||||
Reaction {
|
||||
output: ChemicalAmount {
|
||||
chemical: "E".to_string(),
|
||||
amount: 1,
|
||||
},
|
||||
inputs: vec![
|
||||
ChemicalAmount {
|
||||
chemical: "A".to_string(),
|
||||
amount: 7,
|
||||
},
|
||||
ChemicalAmount {
|
||||
chemical: "D".to_string(),
|
||||
amount: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
(
|
||||
"A".to_string(),
|
||||
Reaction {
|
||||
output: ChemicalAmount {
|
||||
chemical: "A".to_string(),
|
||||
amount: 10,
|
||||
},
|
||||
inputs: vec![ChemicalAmount {
|
||||
chemical: "ORE".to_string(),
|
||||
amount: 10,
|
||||
}],
|
||||
},
|
||||
),
|
||||
(
|
||||
"D".to_string(),
|
||||
Reaction {
|
||||
output: ChemicalAmount {
|
||||
chemical: "D".to_string(),
|
||||
amount: 1,
|
||||
},
|
||||
inputs: vec![
|
||||
ChemicalAmount {
|
||||
chemical: "A".to_string(),
|
||||
amount: 7,
|
||||
},
|
||||
ChemicalAmount {
|
||||
chemical: "C".to_string(),
|
||||
amount: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
(
|
||||
"FUEL".to_string(),
|
||||
Reaction {
|
||||
output: ChemicalAmount {
|
||||
chemical: "FUEL".to_string(),
|
||||
amount: 1,
|
||||
},
|
||||
inputs: vec![
|
||||
ChemicalAmount {
|
||||
chemical: "A".to_string(),
|
||||
amount: 7,
|
||||
},
|
||||
ChemicalAmount {
|
||||
chemical: "E".to_string(),
|
||||
amount: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
(
|
||||
"B".to_string(),
|
||||
Reaction {
|
||||
output: ChemicalAmount {
|
||||
chemical: "B".to_string(),
|
||||
amount: 1,
|
||||
},
|
||||
inputs: vec![ChemicalAmount {
|
||||
chemical: "ORE".to_string(),
|
||||
amount: 1,
|
||||
}],
|
||||
},
|
||||
),
|
||||
(
|
||||
"C".to_string(),
|
||||
Reaction {
|
||||
output: ChemicalAmount {
|
||||
chemical: "C".to_string(),
|
||||
amount: 1,
|
||||
},
|
||||
inputs: vec![
|
||||
ChemicalAmount {
|
||||
chemical: "A".to_string(),
|
||||
amount: 7,
|
||||
},
|
||||
ChemicalAmount {
|
||||
chemical: "B".to_string(),
|
||||
amount: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reads_reactions() {
|
||||
assert_eq!(read_reactions(TEST_INPUT1).unwrap(), reactions_1());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn solves_part1() {
|
||||
assert_eq!(solve_part1(TEST_INPUT1).unwrap(), 31);
|
||||
assert_eq!(solve_part1(TEST_INPUT2).unwrap(), 165);
|
||||
assert_eq!(solve_part1(TEST_INPUT3).unwrap(), 13312);
|
||||
assert_eq!(solve_part1(TEST_INPUT4).unwrap(), 180697);
|
||||
assert_eq!(solve_part1(TEST_INPUT5).unwrap(), 2210736);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user