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 size = report.len();
42 let score: i32 = report.windows(2).map(|w| delta(w[0], w[1])).sum();
43
44 if score.abs() == (size - 1) as i32 {
45 return (1, 1);
46 }
47
48 for i in 0..size {
49 let mut score = score;
50
51 if i > 0 {
53 score -= delta(report[i - 1], report[i]);
54 }
55 if i < size - 1 {
56 score -= delta(report[i], report[i + 1]);
57 }
58 if i > 0 && i < size - 1 {
59 score += delta(report[i - 1], report[i + 1]);
60 }
61
62 if score.abs() == (size - 2) as i32 {
63 return (0, 1);
64 }
65 }
66
67 (0, 0)
68}
69
70fn delta(a: i32, b: i32) -> i32 {
72 let diff = b - a;
73 (diff.abs() <= 3) as i32 * diff.signum()
74}