1use utils::prelude::*;
2
3#[derive(Clone, Debug)]
5pub struct Day07 {
6 part1: u64,
7 part2: u64,
8}
9
10impl Day07 {
11 pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
12 let mut seen_start = false;
13 let mut timeline_counts = Vec::new();
14 let mut split_count = 0;
15
16 for line in input.lines() {
17 if timeline_counts.is_empty() {
18 timeline_counts.resize(line.len() + 2, 0);
20 } else if timeline_counts.len() != line.len() + 2 {
21 return Err(InputError::new(
22 input,
23 line,
24 "expected consistent line lengths",
25 ));
26 }
27
28 for (i, b) in line.bytes().enumerate() {
29 let c = i + 1;
30
31 match b {
32 b'^' if timeline_counts[c] > 0 => {
33 timeline_counts[c - 1] += timeline_counts[c];
34 timeline_counts[c + 1] += timeline_counts[c];
35 timeline_counts[c] = 0;
36 split_count += 1;
37 }
38 b'.' | b'^' => {}
39 b'S' if !seen_start => {
40 timeline_counts[c] += 1;
41 seen_start = true;
42 }
43 b'S' => return Err(InputError::new(input, line, "expected one 'S'")),
44 _ => return Err(InputError::new(input, line, "expected '.', '^' or 'S'")),
45 }
46 }
47 }
48
49 Ok(Self {
50 part1: split_count,
51 part2: timeline_counts.iter().sum(),
52 })
53 }
54
55 #[must_use]
56 pub fn part1(&self) -> u64 {
57 self.part1
58 }
59
60 #[must_use]
61 pub fn part2(&self) -> u64 {
62 self.part2
63 }
64}
65
66examples!(Day07 -> (u64, u64) [
67 {file: "day07_example0.txt", part1: 21, part2: 40},
68]);