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::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 reflect_axis(columns, target)
57 .unwrap_or_else(|| 100 * reflect_axis(rows, target).unwrap())
58 })
59 .sum()
60}
61
62fn reflect_axis(axis: &[u32], target: u32) -> Option<usize> {
63 let size = axis.len();
64
65 (1..size).find(|&i| {
66 let smudges: u32 =
68 (0..i.min(size - i)).map(|j| (axis[i - j - 1] ^ axis[i + j]).count_ones()).sum();
69
70 smudges == target
71 })
72}