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