This commit is contained in:
Quentin Boyer 2024-12-07 23:12:31 +01:00
parent 40b926347b
commit 585eefd437

116
src/bin/day7.rs Normal file
View file

@ -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<u64>)>;
#[inline(never)]
pub fn parsing(input: &BString) -> color_eyre::Result<Parsed> {
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::<Result<_, _>>()
.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(())
}