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
103
104
105
106
107
108
109
110
111
112
113
114
|
#![allow(dead_code)]
#![allow(unused_variables)]
use advent_of_code::prelude::*;
pub fn parse(fh: File) -> Result<Grid<u8>> {
Ok(parse::grid(parse::raw_lines(fh), |c, _, _| c))
}
pub fn part1(schematic: Grid<u8>) -> Result<i64> {
let mut numbers = vec![];
for row in schematic.each_row() {
let mut current_number = None;
for col in schematic.each_col() {
let c = schematic[row][col];
if c.is_ascii_digit() {
match current_number {
Some(n) => {
current_number = Some(n * 10 + i64::from(c - b'0'))
}
None => current_number = Some(i64::from(c - b'0')),
}
} else if let Some(n) = current_number.take() {
numbers.push((n, row, col));
}
}
if let Some(n) = current_number.take() {
numbers.push((n, row, schematic.cols()));
}
}
let mut total = 0;
'number: for (n, row, col) in numbers {
let len = n.ilog10() + 1;
for offset in 0..=n.ilog10() {
let col = Col(col.0 - usize::try_from(offset).unwrap() - 1);
for (row, col) in schematic.adjacent(row, col, true) {
let c = schematic[row][col];
if !c.is_ascii_digit() && c != b'.' {
total += n;
continue 'number;
}
}
}
}
Ok(total)
}
pub fn part2(schematic: Grid<u8>) -> Result<i64> {
let mut numbers = vec![];
for row in schematic.each_row() {
let mut current_number = None;
for col in schematic.each_col() {
let c = schematic[row][col];
if c.is_ascii_digit() {
match current_number {
Some(n) => {
current_number = Some(n * 10 + i64::from(c - b'0'))
}
None => current_number = Some(i64::from(c - b'0')),
}
} else if let Some(n) = current_number.take() {
numbers.push((n, row, col));
}
}
if let Some(n) = current_number.take() {
numbers.push((n, row, schematic.cols()));
}
}
let mut gears: HashMap<_, HashSet<_>> = HashMap::new();
for (n, nrow, ncol) in numbers {
let len = n.ilog10() + 1;
for offset in 0..=n.ilog10() {
for (grow, gcol) in schematic.adjacent(
nrow,
Col(ncol.0 - usize::try_from(offset).unwrap() - 1),
true,
) {
let c = schematic[grow][gcol];
if c == b'*' {
gears
.entry((grow, gcol))
.or_default()
.insert((n, nrow, ncol));
}
}
}
}
Ok(gears
.values()
.filter_map(|s| {
if s.len() == 2 {
Some(s.iter().map(|(n, _, _)| n).product::<i64>())
} else {
None
}
})
.sum())
}
#[test]
fn test() {
assert_eq!(
part1(parse(parse::data(2023, 3).unwrap()).unwrap()).unwrap(),
540212
);
assert_eq!(
part2(parse(parse::data(2023, 3).unwrap()).unwrap()).unwrap(),
87605697
);
}
|