1use utils::prelude::*;
2
3#[derive(Clone, Debug)]
5pub struct Day03<'a> {
6 lines: Vec<&'a [u8]>,
7}
8
9impl<'a> Day03<'a> {
10 pub fn new(input: &'a str, _: InputType) -> Result<Self, InputError> {
11 let lines: Vec<&[u8]> = input.lines().map(str::as_bytes).collect();
12 for &line in &lines {
13 if let Some(&b) = line.iter().find(|x| !matches!(x, b'1'..=b'9')) {
14 return Err(InputError::new(input, b as char, "expected digit 1-9"));
15 }
16 if line.len() < 12 {
17 return Err(InputError::new(input, line, "expected at least 12 digits"));
18 }
19 }
20 Ok(Self { lines })
21 }
22
23 #[must_use]
24 pub fn part1(&self) -> u64 {
25 self.output_joltage::<2>()
26 }
27
28 #[must_use]
29 pub fn part2(&self) -> u64 {
30 self.output_joltage::<12>()
31 }
32
33 fn output_joltage<const N: usize>(&self) -> u64 {
34 let mut sum = 0;
35 for line in &self.lines {
36 let (mut start, mut joltage) = (0, 0);
37 for i in 0..N {
38 let (max_byte, start_offset) =
39 line[start..line.len() - N + 1 + i].iter().enumerate().fold(
40 (0, 0),
41 |(max, offset), (i, &b)| {
42 if b > max { (b, i) } else { (max, offset) }
43 },
44 );
45 joltage = (joltage * 10) + (max_byte - b'0') as u64;
46 start += start_offset + 1;
47 }
48 sum += joltage;
49 }
50 sum
51 }
52}
53
54examples!(Day03<'_> -> (u64, u64) [
55 {
56 input: "987654321111111\n811111111111119\n234234234234278\n818181911112111",
57 part1: 357,
58 part2: 3121910778619,
59 },
60]);