1use crate::util::grid::*;
3use crate::util::parse::*;
4use crate::util::point::*;
5
6pub struct Input {
7 grid: Grid<u8>,
8 seen: Grid<usize>,
9 parts: Vec<u32>,
10}
11
12pub fn parse(input: &str) -> Input {
13 let grid = Grid::parse(input);
14 let mut seen: Grid<usize> = grid.same_size_with(0);
18 let mut parts = vec![0];
20 let mut number = 0;
21
22 for y in 0..grid.height {
23 for x in 0..grid.width {
24 let p = Point::new(x, y);
25 let b = grid[p];
26
27 if b.is_ascii_digit() {
28 seen[p] = parts.len();
30 number = 10 * number + (b.to_decimal() as u32);
31 } else if number > 0 {
32 parts.push(number);
34 number = 0;
35 }
36 }
37 if number > 0 {
39 parts.push(number);
40 number = 0;
41 }
42 }
43
44 Input { grid, seen, parts }
45}
46
47pub fn part1(input: &Input) -> u32 {
49 let Input { grid, seen, parts } = input;
50 let mut parts = parts.clone();
51 let mut result = 0;
52
53 for y in 0..grid.height {
54 for x in 0..grid.width {
55 let p = Point::new(x, y);
56 let b = grid[p];
57
58 if !b.is_ascii_digit() && b != b'.' {
59 for next in DIAGONAL.iter().copied().map(|d| p + d) {
60 let index = seen[next];
61 if index != 0 {
62 result += parts[index];
63 parts[index] = 0;
65 }
66 }
67 }
68 }
69 }
70
71 result
72}
73
74pub fn part2(input: &Input) -> u32 {
76 let Input { grid, seen, parts } = input;
77 let mut result = 0;
78
79 for y in 0..grid.height {
80 for x in 0..grid.width {
81 let p = Point::new(x, y);
82
83 if grid[p] == b'*' {
84 let mut previous = 0;
85 let mut distinct = 0;
86 let mut subtotal = 1;
87
88 for next in DIAGONAL.iter().copied().map(|d| p + d) {
91 let index = seen[next];
92 if index != 0 && index != previous {
93 previous = index;
94 distinct += 1;
95 subtotal *= parts[index];
96 }
97 }
98
99 if distinct == 2 {
100 result += subtotal;
101 }
102 }
103 }
104 }
105
106 result
107}