aoc/year2024/
day08.rs

1//! # Resonant Collinearity
2//!
3//! Antennas frequencies are grouped together to reduce the O(n²) pairwise comparisons.
4use crate::util::grid::*;
5use crate::util::hash::*;
6use crate::util::point::*;
7
8type Input = (Grid<u8>, FastMap<u8, Vec<Point>>);
9
10pub fn parse(input: &str) -> Input {
11    let grid = Grid::parse(input);
12    let mut antennas = FastMap::new();
13
14    for y in 0..grid.height {
15        for x in 0..grid.width {
16            let point = Point::new(x, y);
17            let frequency = grid[point];
18
19            if frequency != b'.' {
20                antennas.entry(frequency).or_insert_with(Vec::new).push(point);
21            }
22        }
23    }
24
25    (grid, antennas)
26}
27
28pub fn part1(input: &Input) -> u32 {
29    let (grid, antennas) = input;
30    let mut locations = grid.same_size_with(0);
31
32    for frequency in antennas.values() {
33        for &first in frequency {
34            for &second in frequency {
35                if first != second {
36                    let distance = second - first;
37                    let antinode = second + distance;
38
39                    if grid.contains(antinode) {
40                        locations[antinode] = 1;
41                    }
42                }
43            }
44        }
45    }
46
47    locations.bytes.iter().sum()
48}
49
50pub fn part2(input: &Input) -> u32 {
51    let (grid, antennas) = input;
52    let mut locations = grid.same_size_with(0);
53
54    for frequency in antennas.values() {
55        for &first in frequency {
56            for &second in frequency {
57                if first != second {
58                    let distance = second - first;
59                    let mut antinode = second;
60
61                    while grid.contains(antinode) {
62                        locations[antinode] = 1;
63                        antinode += distance;
64                    }
65                }
66            }
67        }
68    }
69
70    locations.bytes.iter().sum()
71}