1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
#![allow(dead_code)]
#![allow(unused_variables)]
use advent_of_code::prelude::*;
enum Mirror {
Horizontal(usize),
Vertical(usize),
}
impl Mirror {
fn score(&self) -> usize {
match self {
Self::Horizontal(n) => 100 * n,
Self::Vertical(n) => *n,
}
}
}
fn find_mirror(pattern: &Grid<bool>, smudges: usize) -> Mirror {
'mirror: for row in pattern.each_row().skip(1) {
let mut found_smudges = 0;
for offset in 0..row.min(pattern.rows() - row.0).0 {
let a = pattern.row_vec(row + offset);
let b = pattern.row_vec(row - offset - 1);
found_smudges += a
.into_iter()
.zip(b.into_iter())
.filter(|(a, b)| a != b)
.count();
if found_smudges > smudges {
continue 'mirror;
}
}
if found_smudges != smudges {
continue 'mirror;
}
return Mirror::Horizontal(row.0);
}
'mirror: for col in pattern.each_col().skip(1) {
let mut found_smudges = 0;
for offset in 0..col.min(pattern.cols() - col.0).0 {
let a = pattern.col_vec(col + offset);
let b = pattern.col_vec(col - offset - 1);
found_smudges += a
.into_iter()
.zip(b.into_iter())
.filter(|(a, b)| a != b)
.count();
if found_smudges > smudges {
continue 'mirror;
}
}
if found_smudges != smudges {
continue 'mirror;
}
return Mirror::Vertical(col.0);
}
unreachable!()
}
pub fn parse(fh: File) -> Result<Vec<Grid<bool>>> {
let mut lines = parse::raw_lines(fh).peekable();
let mut grids = vec![];
while lines.peek().is_some() {
grids
.push(parse::grid(parse::chunk(&mut lines), |c, _, _| c == b'#'));
}
Ok(grids)
}
pub fn part1(patterns: Vec<Grid<bool>>) -> Result<i64> {
Ok(patterns
.into_iter()
.map(|pattern| find_mirror(&pattern, 0).score())
.sum::<usize>()
.try_into()
.unwrap())
}
pub fn part2(patterns: Vec<Grid<bool>>) -> Result<i64> {
Ok(patterns
.into_iter()
.map(|pattern| find_mirror(&pattern, 1).score())
.sum::<usize>()
.try_into()
.unwrap())
}
#[test]
fn test() {
assert_eq!(
part1(parse(parse::data(2023, 13).unwrap()).unwrap()).unwrap(),
37975
);
assert_eq!(
part2(parse(parse::data(2023, 13).unwrap()).unwrap()).unwrap(),
32497
);
}
|