Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- pub fn solution(test: bool) -> ((usize, Duration), (usize, Duration)) {
- let lines;
- if test {
- lines = include_str!("../../../AdventOfCodeInputs/problem_inputs_2024/day_8_test.txt");
- } else {
- lines = include_str!("../../../AdventOfCodeInputs/problem_inputs_2024/day_8.txt");
- }
- let map = Map::from_str(lines);
- (
- solve(&map, Map::generate_antinodes_p1),
- solve(&map, Map::generate_antinodes_p2),
- )
- }
- fn solve(
- map: &Map,
- generator: impl Fn(&Map) -> FxHashSet<(RowIndex, ColIndex)>,
- ) -> (usize, Duration) {
- let now = Instant::now();
- let mut antinodes = FxHashSet::default();
- for freq in map.get_unique_freqs() {
- let filtered_map = map.filter_freq(freq);
- let specific_antinodes = generator(&filtered_map);
- antinodes = antinodes
- .union(&specific_antinodes)
- .map(|f| *f)
- .collect::<FxHashSet<_>>();
- }
- let ans = antinodes.len();
- (ans, now.elapsed())
- }
- type RowIndex = isize;
- type ColIndex = isize;
- #[derive(Debug, Clone)]
- struct Map {
- freq_if_unique: Option<char>,
- antennae: FxHashMap<(RowIndex, ColIndex), char>,
- bounds: (usize, usize),
- }
- impl Map {
- fn from_str(lines: &str) -> Self {
- let mut antennae = FxHashMap::default();
- lines.lines().enumerate().for_each(|(row, line)| {
- line.chars().enumerate().for_each(|(col, c)| {
- if c != '.' {
- antennae.insert((row as isize, col as isize), c);
- }
- });
- });
- Self {
- freq_if_unique: None,
- antennae,
- bounds: (lines.lines().count(), lines.lines().next().unwrap().len()),
- }
- }
- fn get_unique_freqs(&self) -> Vec<char> {
- let mut freqs = Vec::new();
- self.antennae.values().for_each(|&c| {
- if !freqs.contains(&c) {
- freqs.push(c);
- }
- });
- freqs
- }
- fn filter_freq(&self, char: char) -> Self {
- let antennae = self
- .antennae
- .iter()
- .filter(|(_, &c)| c == char)
- .map(|(&k, &v)| (k, v))
- .collect();
- Self {
- freq_if_unique: Some(char),
- antennae,
- bounds: self.bounds,
- }
- }
- fn generate_antinodes_p1(&self) -> FxHashSet<(RowIndex, ColIndex)> {
- let mut antinodes: FxHashSet<(RowIndex, ColIndex)> = FxHashSet::default();
- let node_pairs = self.antennae.keys().combinations(2);
- for pair in node_pairs {
- let (node1, node2) = (pair[0], pair[1]);
- let (row1, col1) = node1;
- let (row2, col2) = node2;
- let vec = (row2 - row1, col2 - col1);
- let mut point = (row1 + vec.0, col1 + vec.1);
- while point.0 >= 0
- && point.0 < self.bounds.0 as isize
- && point.1 >= 0
- && point.1 < self.bounds.1 as isize
- {
- let distance_1 = distance(node1, &point);
- let distance_2 = distance(node2, &point);
- if check_distance(distance_1, distance_2) {
- antinodes.insert(point);
- }
- point = (point.0 + vec.0, point.1 + vec.1);
- }
- let mut point = (row1 - vec.0, col1 - vec.1);
- while point.0 >= 0
- && point.0 < self.bounds.0 as isize
- && point.1 >= 0
- && point.1 < self.bounds.1 as isize
- {
- let distance_1 = distance(node1, &point);
- let distance_2 = distance(node2, &point);
- if check_distance(distance_1, distance_2) {
- antinodes.insert(point);
- }
- point = (point.0 - vec.0, point.1 - vec.1);
- }
- }
- antinodes
- }
- fn generate_antinodes_p2(&self) -> FxHashSet<(RowIndex, ColIndex)> {
- let mut antinodes: FxHashSet<(RowIndex, ColIndex)> = FxHashSet::default();
- let node_pairs = self.antennae.keys().combinations(2);
- for pair in node_pairs {
- let (node1, node2) = (pair[0], pair[1]);
- let (row1, col1) = node1;
- let (row2, col2) = node2;
- let vec = (row2 - row1, col2 - col1);
- let mut point = (*row1, *col1);
- while point.0 >= 0
- && point.0 < self.bounds.0 as isize
- && point.1 >= 0
- && point.1 < self.bounds.1 as isize
- {
- antinodes.insert(point);
- point = (point.0 + vec.0, point.1 + vec.1);
- }
- let mut point = (*row1, *col1);
- while point.0 >= 0
- && point.0 < self.bounds.0 as isize
- && point.1 >= 0
- && point.1 < self.bounds.1 as isize
- {
- antinodes.insert(point);
- point = (point.0 - vec.0, point.1 - vec.1);
- }
- }
- antinodes
- }
- }
- const fn distance(
- (row1, col1): &(RowIndex, ColIndex),
- (row2, col2): &(RowIndex, ColIndex),
- ) -> usize {
- ((*row1 - *row2).abs() + (*col1 - *col2).abs()) as usize
- }
- const fn check_distance(distance_1: usize, distance_2: usize) -> bool {
- distance_1 * 2 == distance_2 || distance_2 * 2 == distance_1
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement