diff --git a/src/bin/day7.rs b/src/bin/day7.rs new file mode 100644 index 0000000..02c3f1f --- /dev/null +++ b/src/bin/day7.rs @@ -0,0 +1,116 @@ +use std::time::Instant; + +use aoc_2024::{load, print_res}; +use bstr::BString; +use color_eyre::eyre::Context; + +type Parsed = Vec<(u64, Vec)>; + +#[inline(never)] +pub fn parsing(input: &BString) -> color_eyre::Result { + core::str::from_utf8(input)? + .lines() + .map(|line| { + let Some((result, values)) = line.split_once(':') else { + color_eyre::eyre::bail!("Missing `:` in '{line}'"); + }; + + Ok(( + result.parse().with_context(|| "could not parse result")?, + values + .split_whitespace() + .map(|n| n.parse().with_context(|| "could not parse value `{n}`")) + .collect::>() + .with_context(|| "could not parse values")?, + )) + }) + .collect() +} + +#[inline(never)] +pub fn part1(input: Parsed) { + let mut total_calibration_result = 0; + + for (result, values) in input { + let mut totals = vec![values[0]]; + + for v in &values[1..] { + let mut new = Vec::with_capacity(totals.len() * 2); + for total in totals { + let p = total + v; + if p <= result { + new.push(p); + } + + let m = total * v; + if m <= result { + new.push(m); + } + } + totals = new; + } + + if totals.contains(&result) { + total_calibration_result += result; + } + } + + print_res!("Total calibration result: {total_calibration_result}") +} + +#[inline(never)] +pub fn part2(input: Parsed) { + let mut total_calibration_result = 0; + + for (result, values) in input { + let mut totals = vec![values[0]]; + + for v in &values[1..] { + let mut new = Vec::with_capacity(totals.len() * 3); + for total in totals { + let p = total + v; + if p <= result { + new.push(p); + } + + let m = total * v; + if m <= result { + new.push(m); + } + + let c = total * 10u64.pow(v.ilog10() + 1) + v; + if c <= result { + new.push(c); + } + } + totals = new; + } + + if totals.contains(&result) { + total_calibration_result += result; + } + } + + print_res!("Total calibration result: {total_calibration_result}") +} + +pub fn main() -> color_eyre::Result<()> { + let context = load()?; + + let start = Instant::now(); + let parsed = parsing(&context.input)?; + let elapsed = humantime::format_duration(start.elapsed()); + + let start = Instant::now(); + if context.part == 1 { + part1(parsed); + } else { + part2(parsed); + } + let elapsed_part = humantime::format_duration(start.elapsed()); + + println!(" Parsing: {elapsed}"); + println!(" Solving: {elapsed_part}"); + + Ok(()) +}