diff --git a/Cargo.lock b/Cargo.lock index 32e1562..5c62c2d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -38,6 +38,13 @@ dependencies = [ "winnow", ] +[[package]] +name = "day07" +version = "0.1.0" +dependencies = [ + "winnow", +] + [[package]] name = "memchr" version = "2.7.4" diff --git a/Cargo.toml b/Cargo.toml index 8db5cad..9369029 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace] resolver = "2" -members = ["day01", "day02", "day03", "day04", "day05", "day06"] +members = ["day01", "day02", "day03", "day04", "day05", "day06", "day07"] [workspace.dependencies] winnow = "0.6" diff --git a/day07/Cargo.toml b/day07/Cargo.toml new file mode 100644 index 0000000..3f5d565 --- /dev/null +++ b/day07/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "day07" +version = "0.1.0" +edition = "2024" + +[dependencies] +winnow.workspace = true diff --git a/day07/src/main.rs b/day07/src/main.rs new file mode 100644 index 0000000..e48207e --- /dev/null +++ b/day07/src/main.rs @@ -0,0 +1,132 @@ +use std::collections::HashSet; + +use winnow::{ + PResult, Parser, + ascii::{dec_uint, newline, space1}, + combinator::{eof, opt, separated, separated_pair, seq}, +}; + +fn main() { + let input = std::fs::read_to_string("input").unwrap(); + println!("{}", pt1(&input)); + println!("{}", pt2(&input)); +} + +fn pt1(input: &str) -> u64 { + let mut total = 0; + let eqs = parse(input); + for eq in &eqs { + if check(eq) { + total += eq.total; + } + } + total +} + +fn pt2(_input: &str) -> u64 { + let mut total = 0; + + total +} + +#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)] +struct Equation { + total: u64, + factors: Vec, +} + +impl Equation { + pub fn next(&self, cur: usize) -> Option<(usize, u64)> { + let next_idx = cur + 1; + self.factors.get(next_idx).copied().map(|v| (next_idx, v)) + } + + pub fn first(&self) -> (usize, u64) { + (0, self.factors[0]) + } +} + +fn check(equation: &Equation) -> bool { + let mut processed = HashSet::new(); + let mut q = Vec::new(); + let target = equation.total; + + q.push(equation.first()); + while let Some(current) = q.pop() { + if !processed.contains(¤t) { + q.push(current); + } + + let (cur_idx, cur_val) = current; + + let mut process_top = true; + if let Some((next_idx, next_val)) = equation.next(cur_idx) { + let plus = (next_idx, cur_val + next_val); + let mul = (next_idx, cur_val * next_val); + if mul.1 <= target && !processed.contains(&mul) { + process_top = false; + q.push(mul); + } + if plus.1 <= target && !processed.contains(&plus) { + process_top = false; + q.push(plus); + } + } + if process_top { + let _ = q.pop(); + if cur_val == target { + return true; + } + processed.insert(current); + } + } + + false +} + +fn parse_equation(input: &mut &str) -> PResult { + let (total, factors) = separated_pair( + dec_uint, + ": ", + separated(1.., dec_uint::<_, u64, _>, space1), + ) + .parse_next(input)?; + + Ok(Equation { total, factors }) +} + +fn parse(input: &str) -> Vec { + let (equations, _): (Vec, _) = seq!( + separated(1.., parse_equation, newline), + seq!(opt(newline), opt(eof)) + ) + .parse(input) + .unwrap(); + equations +} + +#[cfg(test)] +mod test { + use super::*; + + static TEST_INPUT: &str = "190: 10 19 +3267: 81 40 27 +83: 17 5 +156: 15 6 +7290: 6 8 6 15 +161011: 16 10 13 +192: 17 8 14 +21037: 9 7 18 13 +292: 11 6 16 20"; + + #[test] + fn p1() { + let v = pt1(TEST_INPUT); + assert_eq!(v, 3749) + } + + #[test] + fn p2() { + assert_eq!(0, pt2(TEST_INPUT)); + } +}