1use crate::util::parse::*;
16
17type Input = (u32, u32);
18
19pub fn parse(input: &str) -> Input {
21 let mut report = Vec::new();
22
23 input.lines().fold((0, 0), |(part_one, part_two), line| {
24 report.clear();
25 report.extend(line.iter_signed::<i32>());
26
27 let (p1, p2) = check(&report);
28 (part_one + p1, part_two + p2)
29 })
30}
31
32pub fn part1(input: &Input) -> u32 {
33 input.0
34}
35
36pub fn part2(input: &Input) -> u32 {
37 input.1
38}
39
40fn check(report: &[i32]) -> (u32, u32) {
41 let end = report.len() - 1;
42 let target = end as i32;
43 let score: i32 = report.array_windows().map(|&[a, b]| delta(a, b)).sum();
44
45 if score.abs() == target {
46 return (1, 1);
47 }
48
49 let dampened = (0..=end).any(|i| {
50 let mut score = score;
51
52 if i > 0 {
54 score -= delta(report[i - 1], report[i]);
55 }
56 if i < end {
57 score -= delta(report[i], report[i + 1]);
58 }
59 if i > 0 && i < end {
60 score += delta(report[i - 1], report[i + 1]);
61 }
62
63 score.abs() == target - 1
64 });
65
66 (0, u32::from(dampened))
67}
68
69fn delta(a: i32, b: i32) -> i32 {
71 match b - a {
72 1..=3 => 1,
73 -3..=-1 => -1,
74 _ => 0,
75 }
76}