use crate::prelude::*; mod prelude; fn main() { Day1::show(day_input(1), day_input(1)) } struct Day1 {} impl Day1 { fn calibration_value(line: &str) -> i128 { println!("{line}"); let bytes = line.as_bytes(); let mut first_digit: Option = None; let mut last_digit: Option = None; for i in 0..bytes.len() { let n = bytes.len() - 1 - i; println!("{n} {i}"); if first_digit.is_none() && (0x30..=0x39).contains(&bytes[i]) { first_digit = Some(bytes[i] - 0x30); println!("found first {first_digit:?}"); } if last_digit.is_none() && (0x30..=0x39).contains(&bytes[n]) { last_digit = Some(bytes[n] - 0x30); println!("found last {last_digit:?}"); } if first_digit.is_some() && last_digit.is_some() { break; } } println!("{:?} {:?}", first_digit, last_digit); Into::::into(first_digit.or(last_digit).unwrap() * 10) + Into::::into(last_digit.or(first_digit).unwrap()) } fn num_name(s: &[u8]) -> Option { for (i, w) in [ "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", ] .map(|s| s.as_bytes()) .iter() .enumerate() { if s.starts_with(w) { return Some(i as u8); } } return None; } fn num_name_end(s: &[u8]) -> Option { for (i, w) in [ "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", ] .map(|s| s.as_bytes()) .iter() .enumerate() { if s.ends_with(w) { return Some(i as u8); } } return None; } fn calibration_value_words(line: &str) -> i128 { println!("{line}"); let bytes = line.as_bytes(); let mut first_digit: Option = None; let mut last_digit: Option = None; for i in 0..bytes.len() { let n = bytes.len() - 1 - i; println!("NI: {n} {i}"); if first_digit.is_none() { if (0x30..=0x39).contains(&bytes[i]) { first_digit = Some(bytes[i] - 0x30); println!("found first {first_digit:?}"); } else if let Some(n) = Self::num_name(&bytes[i..]) { first_digit = Some(n); println!("found first text {first_digit:?}"); } } if last_digit.is_none() { println!("{:?}", &bytes[..=n]); if (0x30..=0x39).contains(&bytes[n]) { last_digit = Some(bytes[n] - 0x30); println!("found last {last_digit:?}"); } else if let Some(n) = Self::num_name_end(&bytes[..=n]) { last_digit = Some(n); println!("found last text {last_digit:?}"); } } if first_digit.is_some() && last_digit.is_some() { break; } } println!("{:?} {:?}", first_digit, last_digit); Into::::into(first_digit.or(last_digit).unwrap() * 10) + Into::::into(last_digit.or(first_digit).unwrap()) } } impl AoCSolution for Day1 { type Input = String; type Solution = i128; fn part1(input: Self::Input) -> Self::Solution { input.lines().map(Self::calibration_value).sum() } fn part2(input: Self::Input) -> Self::Solution { input.lines().map(Self::calibration_value_words).sum() } } #[cfg(test)] mod tests { use super::*; #[test] fn test() { assert_eq!( Day1::part1( r#"1abc2 pqr3stu8vwx a1b2c3d4e5f treb7uchet"# .into() ), 142 ); assert_eq!( Day1::part2( r#"two1nine eightwothree abcone2threexyz xtwone3four 4nineeightseven2 zoneight234 7pqrstsixteen"# .into() ), 281 ); } }