Skip to content

Commit

Permalink
[2024] Day 8 initial solution
Browse files Browse the repository at this point in the history
  • Loading branch information
connorslade committed Dec 8, 2024
1 parent a1a2859 commit 683946f
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Thank you to [Eric Wastl](http://was.tl) for running this incredible yearly even
- [Day 05: Print Queue](aoc_2024/src/day_05.rs)
- [Day 06: Guard Gallivant](aoc_2024/src/day_06.rs)
- [Day 07: Bridge Repair](aoc_2024/src/day_07.rs)
- [Day 08: Resonant Collinearity](aoc_2024/src/day_08.rs)
<!-- MARKER -->

## [2023](https://adventofcode.com/2023) [![aoc_2023](https://github.com/connorslade/advent-of-code/actions/workflows/aoc_2023.yml/badge.svg)](https://github.com/connorslade/advent-of-code/actions/workflows/aoc_2023.yml)
Expand Down
150 changes: 150 additions & 0 deletions aoc_2024/src/day_08.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
use std::collections::{HashMap, HashSet};

use aoc_lib::matrix::Matrix;
use common::{solution, Answer};
use nd_vec::{vector, Vec2};

use itertools::Itertools;

solution!("Resonant Collinearity", 8);

#[derive(Clone)]
enum Tile {
Emitter(char),
Empty,
}

fn part_a(input: &str) -> Answer {
let world = Matrix::new_chars(input, |x| match x {
'a'..='z' | 'A'..='Z' | '0'..='9' => Tile::Emitter(x),
_ => Tile::Empty,
});

let mut freqs = HashMap::<char, Vec<Vec2<i32>>>::new();

// oh god just make a Matrix.iter function at this point...
for x in 0..world.size.x() {
for y in 0..world.size.y() {
let pos = vector!(x, y);
if let Tile::Emitter(chr) = world.get(pos).unwrap() {
freqs
.entry(*chr)
.or_default()
.push(pos.try_cast::<i32>().unwrap());
}
}
}

// nodes are on the line between two of the same freq emitters when d1 = 2*d2
// to find nodes, start by finding all lines through matching emitters

let in_bounds = |pos: Vec2<i32>| {
pos.x() >= 0
&& pos.y() >= 0
&& pos.x() < world.size.x() as i32
&& pos.y() < world.size.y() as i32
};

let mut out = HashSet::new();
for (_freq, pos) in freqs {
for (a, b) in pos.into_iter().tuple_combinations() {
let diff_a = a + (a - b);
let diff_b = b + (b - a);

if in_bounds(diff_a) {
out.insert(diff_a);
}

if in_bounds(diff_b) {
out.insert(diff_b);
}
}
}

out.len().into()
}

fn part_b(input: &str) -> Answer {
let world = Matrix::new_chars(input, |x| match x {
'a'..='z' | 'A'..='Z' | '0'..='9' => Tile::Emitter(x),
_ => Tile::Empty,
});

let mut freqs = HashMap::<char, Vec<Vec2<i32>>>::new();

// oh god just make a Matrix.iter function at this point...
for x in 0..world.size.x() {
for y in 0..world.size.y() {
let pos = vector!(x, y);
if let Tile::Emitter(chr) = world.get(pos).unwrap() {
freqs
.entry(*chr)
.or_default()
.push(pos.try_cast::<i32>().unwrap());
}
}
}

// nodes are on the line between two of the same freq emitters when d1 = 2*d2
// to find nodes, start by finding all lines through matching emitters

let in_bounds = |pos: Vec2<i32>| {
pos.x() >= 0
&& pos.y() >= 0
&& pos.x() < world.size.x() as i32
&& pos.y() < world.size.y() as i32
};

let mut out = HashSet::new();
for (_freq, pos) in freqs {
for (a, b) in pos.into_iter().tuple_combinations() {
let diff_a = a - b;
let diff_b = b - a;

let mut pos_a = a;
let mut pos_b = b;

while in_bounds(pos_a) {
out.insert(pos_a);
pos_a += diff_a;
}

while in_bounds(pos_b) {
out.insert(pos_b);
pos_b += diff_b;
}
}
}

out.len().into()
}

#[cfg(test)]
mod test {
use indoc::indoc;

const CASE: &str = indoc! {"
............
........0...
.....0......
.......0....
....0.......
......A.....
............
............
........A...
.........A..
............
............
"};

#[test]
fn part_a() {
assert_eq!(super::part_a(CASE), 14.into());
}

#[test]
fn part_b() {
assert_eq!(super::part_b(CASE), 34.into());
}
}
2 changes: 2 additions & 0 deletions aoc_2024/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ mod day_04;
mod day_05;
mod day_06;
mod day_07;
mod day_08;
// [import_marker]

pub const SOLUTIONS: &[Solution] = &[
Expand All @@ -17,5 +18,6 @@ pub const SOLUTIONS: &[Solution] = &[
day_05::SOLUTION,
day_06::SOLUTION,
day_07::SOLUTION,
day_08::SOLUTION,
// [list_marker]
];

0 comments on commit 683946f

Please sign in to comment.