advent of code 2025
adventofcode.com/2025
aoc
rust
1use anyhow::Context;
2
3const INPUT: &str = include_str!("input/3/actual.txt");
4
5const IS_PART_2: bool = true;
6
7const LENGTH: usize = if IS_PART_2 { 12 } else { 2 };
8
9pub fn main() -> anyhow::Result<()> {
10 let banks = parse(INPUT).context("parsing input")?;
11
12 let mut total: u64 = 0;
13
14 for bank in banks {
15 total += max_joltage_from_bank(&bank, LENGTH);
16 }
17
18 println!("{:?}", total);
19
20 Ok(())
21}
22
23fn max_joltage_from_bank(bank: &[u8], length: usize) -> u64 {
24 let bank_length = bank.len();
25 assert!(
26 length <= bank_length,
27 "cannot choose {length} digits from a bank of length {bank_length}"
28 );
29
30 let mut to_remove = bank_length - length;
31 let mut stack: Vec<u8> = Vec::with_capacity(bank_length);
32
33 for &digit in bank {
34 while to_remove > 0 && !stack.is_empty() && *stack.last().unwrap() < digit {
35 stack.pop();
36 to_remove -= 1;
37 }
38
39 stack.push(digit);
40 }
41
42 stack.truncate(length);
43
44 stack.into_iter().fold(0u64, |acc, d| acc * 10 + d as u64)
45}
46
47fn parse(input: &str) -> anyhow::Result<Vec<Vec<u8>>> {
48 let mut banks: Vec<Vec<u8>> = Vec::new();
49 for line in input.trim().lines() {
50 let mut bank: Vec<u8> = Vec::with_capacity(line.len());
51 for character in line.chars() {
52 let joltage = character
53 .to_string()
54 .parse::<u8>()
55 .context(format!("parsing {} as u8", character))?;
56 bank.push(joltage);
57 }
58 banks.push(bank);
59 }
60 Ok(banks)
61}