at main 1.6 kB view raw
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}