This commit is contained in:
traxys 2025-12-03 14:29:05 +01:00
parent 2be9fa8aba
commit 6fd57bcc6d

115
src/bin/day3.rs Normal file
View file

@ -0,0 +1,115 @@
use std::time::Instant;
use aoc_2025::{load, print_res};
use bstr::{BStr, BString, ByteSlice};
type Parsed<'a> = Vec<Bank<'a>>;
const MAX_JOLT_LEN: usize = 12;
pub struct Bank<'a> {
values: &'a BStr,
joltage_cache: [Vec<usize>; MAX_JOLT_LEN],
}
impl<'a> Bank<'a> {
fn max_joltage_from(&mut self, len: usize, from: usize) -> usize {
assert!(len <= MAX_JOLT_LEN);
assert!(len > 0);
if self.joltage_cache[len - 1][from] != 0 {
return self.joltage_cache[len - 1][from];
}
let &largest_hi = self
.values
.iter()
.take(self.values.len() - (len - 1))
.skip(from)
.max()
.unwrap();
if len == 1 {
let val = (largest_hi - b'0') as usize;
self.joltage_cache[len - 1][from] = val;
return val;
}
let mut max = 0;
for (i, _) in self
.values
.iter()
.enumerate()
.take(self.values.len() - (len - 1))
.skip(from)
.filter(|&(_, &v)| v == largest_hi)
{
let largest_low = self.max_joltage_from(len - 1, i + 1);
let joltage = (largest_hi - b'0') as usize * 10usize.pow(len as u32 - 1) + largest_low;
max = max.max(joltage);
}
self.joltage_cache[len - 1][from] = max;
max
}
pub fn max_joltage(&mut self, len: usize) -> usize {
self.max_joltage_from(len, 0)
}
}
#[inline(never)]
pub fn parsing(input: &BString) -> color_eyre::Result<Parsed<'_>> {
Ok(input
.lines()
.map(|v| Bank {
values: v.as_bstr(),
joltage_cache: std::array::from_fn(|_| vec![0; v.len()]),
})
.collect())
}
#[inline(never)]
pub fn part1(input: Parsed) {
let mut joltage_sum = 0;
for mut bank in input {
joltage_sum += bank.max_joltage(2);
}
print_res!("Maximum total joltage: {joltage_sum}");
}
#[inline(never)]
pub fn part2(input: Parsed) {
let mut joltage_sum = 0;
for mut bank in input {
joltage_sum += bank.max_joltage(12);
}
print_res!("Maximum total joltage: {joltage_sum}");
}
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(())
}