Day 8

This commit is contained in:
LeMoonStar 2024-12-08 19:32:09 +01:00
parent f5d44b9672
commit 3322e07163
3 changed files with 202 additions and 13 deletions

View file

@ -3,8 +3,8 @@
[![About](https://img.shields.io/badge/Advent%20of%20Code-2024-brightgreen?style=flat-square)](https://adventofcode.com/2024/about) [![About](https://img.shields.io/badge/Advent%20of%20Code-2024-brightgreen?style=flat-square)](https://adventofcode.com/2024/about)
[![Language: Rust](https://img.shields.io/badge/Language-Rust-orange.svg?style=flat-square)](https://en.wikipedia.org/wiki/Rust_(programming_language)) [![Language: Rust](https://img.shields.io/badge/Language-Rust-orange.svg?style=flat-square)](https://en.wikipedia.org/wiki/Rust_(programming_language))
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](https://mit-license.org/) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](https://mit-license.org/)
![Days completed](https://img.shields.io/badge/Days%20completed-5%20%2B%202%20half-red?style=flat-square) ![Days completed](https://img.shields.io/badge/Days%20completed-6%20%2B%202%20half-red?style=flat-square)
![Stars](https://img.shields.io/badge/Stars-12-yellow?style=flat-square) ![Stars](https://img.shields.io/badge/Stars-14-yellow?style=flat-square)
> ⚠️ This README is copied from my previous years solution. It is not fully adopted to 2024 yet. > ⚠️ This README is copied from my previous years solution. It is not fully adopted to 2024 yet.

View file

@ -1,32 +1,209 @@
use std::{
collections::{HashMap, HashSet},
ops::{Add, Mul, Sub},
};
use super::{Answer, Day, DayImpl}; use super::{Answer, Day, DayImpl};
const CURRENT_DAY: u8 = 8; const CURRENT_DAY: u8 = 8;
type Data = Vec<u64>; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
struct Vector {
pub x: i64,
pub y: i64,
}
impl Sub for Vector {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
Self {
x: self.x - rhs.x,
y: self.y - rhs.y,
}
}
}
impl Add for Vector {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Self {
x: self.x + rhs.x,
y: self.y + rhs.y,
}
}
}
impl Mul for Vector {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
Self {
x: self.x * rhs.x,
y: self.y * rhs.y,
}
}
}
#[derive(Debug, Clone)]
pub struct AntennaMap {
antenna: HashMap<char, Vec<Vector>>,
limits: Vector,
}
impl AntennaMap {
fn is_in_limits(&self, point: Vector) -> bool {
!(point.x < 0 || point.y < 0 || point.x >= self.limits.x || point.y >= self.limits.y)
}
fn get_antinodes(&self, frequency: char) -> Option<Vec<Vector>> {
let antennas = self.antenna.get(&frequency)?;
let antenna_count = antennas.len();
if antenna_count < 2 {
return Some(vec![]);
}
let mut antinodes = Vec::with_capacity(antenna_count.pow(2) - antenna_count);
for a in 0..antenna_count {
for b in (0..antenna_count).filter(|v| *v != a) {
let new_position =
antennas[a] + (antennas[b] - antennas[a]) * Vector { x: 2, y: 2 };
if self.is_in_limits(new_position) {
antinodes.push(new_position);
}
}
}
Some(antinodes)
}
fn get_resonances(&self, frequency: char) -> Option<Vec<Vector>> {
let antennas = self.antenna.get(&frequency)?;
let antenna_count = antennas.len();
if antenna_count < 2 {
return Some(vec![]);
}
let mut antinodes = Vec::with_capacity(antenna_count.pow(2) - antenna_count);
for a in 0..antenna_count {
for b in (0..antenna_count).filter(|v| *v != a) {
let distance = antennas[b] - antennas[a];
let mut multiplier = 1; // WHYYYY does this have to be 1.... that's just dumb
loop {
let new_position = antennas[a]
+ distance
* Vector {
x: multiplier,
y: multiplier,
};
if !self.is_in_limits(new_position) {
break;
}
antinodes.push(new_position);
multiplier += 1;
}
}
}
Some(antinodes)
}
fn get_all_antinodes(&self) -> Vec<Vector> {
self.antenna
.keys()
.filter_map(|frequency| self.get_antinodes(*frequency))
.flatten()
.collect()
}
fn get_all_resonances(&self) -> Vec<Vector> {
self.antenna
.keys()
.filter_map(|frequency| self.get_resonances(*frequency))
.flatten()
.collect()
}
}
impl From<&str> for AntennaMap {
fn from(value: &str) -> Self {
let lines = value.lines();
let limits = Vector {
y: lines.clone().count() as i64,
x: lines.clone().next().unwrap().len() as i64,
};
Self {
antenna: lines
.enumerate()
.map(|(y, line)| {
(
y,
line.chars()
.enumerate()
.filter(|(_, char)| *char != '.')
.collect::<Vec<_>>(),
)
})
.filter(|(_, line)| line.len() > 0)
.fold(HashMap::new(), |mut map, (y, line)| {
line.into_iter().for_each(|(x, frequency)| {
if let Some(antenna) = map.get_mut(&frequency) {
antenna.push(Vector {
x: x as i64,
y: y as i64,
});
} else {
map.insert(frequency, vec![Vector {
x: x as i64,
y: y as i64,
}]);
}
});
map
}),
limits: limits,
}
}
}
type Data = AntennaMap;
impl DayImpl<Data> for Day<CURRENT_DAY> { impl DayImpl<Data> for Day<CURRENT_DAY> {
fn init_test() -> (Self, Data) { fn init_test() -> (Self, Data) {
Self::init(include_str!("test_inputs/test08.txt")) Self::init(include_str!("test_inputs/test08.txt"))
} }
fn expected_results() -> (Answer, Answer) { fn expected_results() -> (Answer, Answer) {
(Answer::Number(0), Answer::Number(0)) (Answer::Number(14), Answer::Number(34))
} }
fn init(input: &str) -> (Self, Data) { fn init(input: &str) -> (Self, Data) {
( (Self {}, input.into())
Self {},
input
.lines()
.map(|v| v.parse::<u64>().expect("error while parsing input."))
.collect(),
)
} }
fn one(&self, data: &mut Data) -> Answer { fn one(&self, data: &mut Data) -> Answer {
Answer::Number(data.len() as u64) Answer::Number(
data.get_all_antinodes()
.into_iter()
.collect::<HashSet<Vector>>()
.len() as u64,
)
} }
fn two(&self, data: &mut Data) -> Answer { fn two(&self, data: &mut Data) -> Answer {
Answer::Number(data.len() as u64) Answer::Number(
data.get_all_resonances()
.into_iter()
.collect::<HashSet<Vector>>()
.len() as u64,
)
} }
} }

View file

@ -0,0 +1,12 @@
............
........0...
.....0......
.......0....
....0.......
......A.....
............
............
........A...
.........A..
............
............