1use crate::util::grid::*;
21use crate::util::point::*;
22
23type Input = Vec<(Vec<u32>, Vec<u32>)>;
24
25pub fn parse(input: &str) -> Input {
26 input
27 .split("\n\n")
28 .map(|block| {
29 let grid: Grid<_> = Grid::parse(block);
30 let bit = |point| u32::from(grid[point] == b'#');
31
32 let rows: Vec<_> = (0..grid.height)
33 .map(|y| (0..grid.width).fold(0, |n, x| (n << 1) | bit(Point::new(x, y))))
34 .collect();
35 let columns: Vec<_> = (0..grid.width)
36 .map(|x| (0..grid.height).fold(0, |n, y| (n << 1) | bit(Point::new(x, y))))
37 .collect();
38
39 (rows, columns)
40 })
41 .collect()
42}
43
44pub fn part1(input: &Input) -> usize {
45 reflect(input, 0)
46}
47
48pub fn part2(input: &Input) -> usize {
49 reflect(input, 1)
50}
51
52fn reflect(input: &Input, target: u32) -> usize {
53 input
54 .iter()
55 .map(|(rows, columns)| {
56 if let Some(x) = reflect_axis(columns, target) {
57 x
58 } else if let Some(y) = reflect_axis(rows, target) {
59 100 * y
60 } else {
61 unreachable!()
62 }
63 })
64 .sum()
65}
66
67fn reflect_axis(axis: &[u32], target: u32) -> Option<usize> {
68 let size = axis.len();
69
70 (1..size).find(|&i| {
71 let smudges: u32 =
73 (0..i.min(size - i)).map(|j| (axis[i - j - 1] ^ axis[i + j]).count_ones()).sum();
74
75 smudges == target
76 })
77}