mirror of
https://github.com/Rhelvetican/aoc2024.git
synced 2024-12-23 06:51:40 +00:00
day 8
This commit is contained in:
parent
a3f3964e96
commit
9c53f28588
12 changed files with 164 additions and 29 deletions
16
Cargo.lock
generated
16
Cargo.lock
generated
|
@ -75,6 +75,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term",
|
"ansi_term",
|
||||||
"clap",
|
"clap",
|
||||||
|
"itertools",
|
||||||
"paste",
|
"paste",
|
||||||
"regex",
|
"regex",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
@ -126,6 +127,12 @@ version = "1.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
|
@ -138,6 +145,15 @@ version = "1.70.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.7.4"
|
version = "2.7.4"
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ansi_term = "0.12"
|
ansi_term = "0.12"
|
||||||
clap = { version = "4", features = ["derive"] }
|
clap = { version = "4", features = ["derive"] }
|
||||||
|
itertools = "0.13"
|
||||||
paste = "1"
|
paste = "1"
|
||||||
regex = "1"
|
regex = "1"
|
||||||
thiserror = "2"
|
thiserror = "2"
|
||||||
|
|
|
@ -29,6 +29,7 @@ fn main() -> Result<()> {
|
||||||
5 => AocDayFiveSolution,
|
5 => AocDayFiveSolution,
|
||||||
6 => AocDaySixSolution,
|
6 => AocDaySixSolution,
|
||||||
7 => AocDaySevenSolution,
|
7 => AocDaySevenSolution,
|
||||||
|
8 => AocDayEightSolution,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::{collections::HashMap, fs::read_to_string, path::Path};
|
||||||
use super::AocSolution;
|
use super::AocSolution;
|
||||||
use crate::utils::{coord::Coord, Result};
|
use crate::utils::{coord::Coord, Result};
|
||||||
|
|
||||||
const DIRS: [Coord; 8] = [
|
const DIRS: [Coord<i16>; 8] = [
|
||||||
Coord::new(1, 0),
|
Coord::new(1, 0),
|
||||||
Coord::new(1, -1),
|
Coord::new(1, -1),
|
||||||
Coord::new(0, -1),
|
Coord::new(0, -1),
|
||||||
|
@ -15,7 +15,7 @@ const DIRS: [Coord; 8] = [
|
||||||
];
|
];
|
||||||
|
|
||||||
struct XmasGrid {
|
struct XmasGrid {
|
||||||
pub grid: HashMap<Coord, char>,
|
pub grid: HashMap<Coord<i16>, char>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl XmasGrid {
|
impl XmasGrid {
|
||||||
|
@ -29,7 +29,7 @@ impl XmasGrid {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_xmas(&self, pos: Coord) -> usize {
|
fn find_xmas(&self, pos: Coord<i16>) -> usize {
|
||||||
let mut tmp = 0;
|
let mut tmp = 0;
|
||||||
for dir in DIRS {
|
for dir in DIRS {
|
||||||
let mut found = true;
|
let mut found = true;
|
||||||
|
@ -51,7 +51,7 @@ impl XmasGrid {
|
||||||
tmp
|
tmp
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_x_mas(&self, pos: Coord) -> usize {
|
fn find_x_mas(&self, pos: Coord<i16>) -> usize {
|
||||||
let (x, y) = (pos.x, pos.y);
|
let (x, y) = (pos.x, pos.y);
|
||||||
|
|
||||||
let tr = self.grid.get(&Coord::new(x + 1, y + 1));
|
let tr = self.grid.get(&Coord::new(x + 1, y + 1));
|
||||||
|
|
|
@ -10,8 +10,8 @@ use crate::utils::{coord::Coord, direction::Direction, Result};
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct Guard {
|
struct Guard {
|
||||||
dir: Direction,
|
dir: Direction,
|
||||||
cur: Coord,
|
cur: Coord<i16>,
|
||||||
grid: HashMap<Coord, bool>,
|
grid: HashMap<Coord<i16>, bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Guard {
|
impl Guard {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{fs::read_to_string, ops::Mul, path::Path};
|
use std::{fs::read_to_string, path::Path};
|
||||||
|
|
||||||
use super::AocSolution;
|
use super::AocSolution;
|
||||||
use crate::utils::Result;
|
use crate::utils::Result;
|
||||||
|
|
|
@ -1,8 +1,87 @@
|
||||||
use std::{fs::read_to_string, path::Path};
|
use std::{collections::HashMap, fs::read_to_string, path::Path};
|
||||||
|
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
use super::AocSolution;
|
use super::AocSolution;
|
||||||
use crate::utils::Result;
|
use crate::utils::{coord::Coord, Result};
|
||||||
|
|
||||||
|
fn anticoord(a: Coord<i8>, b: Coord<i8>) -> (Coord<i8>, Coord<i8>) {
|
||||||
|
let delta = a - b;
|
||||||
|
(a + delta, b - delta)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map {
|
||||||
|
pub antennas: HashMap<char, Vec<Coord<i8>>>,
|
||||||
|
pub grid: HashMap<Coord<i8>, bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Map {
|
||||||
|
fn new(src: &str) -> Self {
|
||||||
|
let (antennas, grid) = src
|
||||||
|
.lines()
|
||||||
|
.zip(0..)
|
||||||
|
.flat_map(|(line, y)| {
|
||||||
|
line.chars()
|
||||||
|
.zip(0..)
|
||||||
|
.map(move |(ch, x)| (Coord::new(x, y), ch))
|
||||||
|
})
|
||||||
|
.fold(
|
||||||
|
(HashMap::new(), HashMap::new()),
|
||||||
|
|(mut antennas, mut map), (coord, ch)| {
|
||||||
|
if ch != '.' {
|
||||||
|
antennas.entry(ch).or_insert(Vec::new()).push(coord);
|
||||||
|
}
|
||||||
|
|
||||||
|
map.insert(coord, false);
|
||||||
|
|
||||||
|
(antennas, map)
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Self { antennas, grid }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn locations(&mut self) -> u64 {
|
||||||
|
for freq in self.antennas.values() {
|
||||||
|
freq.iter()
|
||||||
|
.tuple_combinations::<(_, _)>()
|
||||||
|
.map(|(&a, &b)| anticoord(a, b))
|
||||||
|
.for_each(|(a, b)| {
|
||||||
|
if let Some(flag) = self.grid.get_mut(&a) {
|
||||||
|
*flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(flag) = self.grid.get_mut(&b) {
|
||||||
|
*flag = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
self.grid.values().filter(|&&x| x).count() as u64
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resonance(&mut self) -> u64 {
|
||||||
|
for freq in self.antennas.values() {
|
||||||
|
freq.iter()
|
||||||
|
.permutations(2)
|
||||||
|
.map(|v| (v[0], v[1]))
|
||||||
|
.filter(|(a, b)| a.ne(b))
|
||||||
|
.for_each(|(&a, &b)| {
|
||||||
|
let dist = b - a;
|
||||||
|
let mut anti = b;
|
||||||
|
|
||||||
|
while let Some(flag) = self.grid.get_mut(&anti) {
|
||||||
|
*flag = true;
|
||||||
|
anti = anti + dist;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
self.grid.values().filter(|&&x| x).count() as u64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
pub struct AocDayEightSolution;
|
pub struct AocDayEightSolution;
|
||||||
|
|
||||||
impl AocSolution for AocDayEightSolution {
|
impl AocSolution for AocDayEightSolution {
|
||||||
|
@ -11,15 +90,17 @@ impl AocSolution for AocDayEightSolution {
|
||||||
fn get_input(&self, path: Option<&Path>) -> Result<String> {
|
fn get_input(&self, path: Option<&Path>) -> Result<String> {
|
||||||
Ok(match path {
|
Ok(match path {
|
||||||
Some(p) => read_to_string(p)?,
|
Some(p) => read_to_string(p)?,
|
||||||
None => read_to_string("./input/day_day_8.txt")?,
|
None => read_to_string("./input/day_8.txt")?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part_one(&self, input: &str) -> Result<Self::Output> {
|
fn part_one(&self, input: &str) -> Result<Self::Output> {
|
||||||
todo!()
|
let mut map = Map::new(input);
|
||||||
|
Ok(map.locations())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part_two(&self, input: &str) -> Result<Self::Output> {
|
fn part_two(&self, input: &str) -> Result<Self::Output> {
|
||||||
todo!()
|
let mut map = Map::new(input);
|
||||||
|
Ok(map.resonance())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +1,41 @@
|
||||||
use std::ops::Add;
|
use std::{
|
||||||
|
fmt::Debug,
|
||||||
|
hash::Hash,
|
||||||
|
ops::{Add, Sub},
|
||||||
|
};
|
||||||
|
|
||||||
use super::direction::Direction;
|
use super::{direction::Direction, Unit};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct Coord {
|
pub struct Coord<U: Unit> {
|
||||||
pub x: i16,
|
pub x: U,
|
||||||
pub y: i16,
|
pub y: U,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Coord {
|
impl<U: Unit> Coord<U> {
|
||||||
pub const fn new(x: i16, y: i16) -> Self {
|
pub const fn new(x: U, y: U) -> Self {
|
||||||
Self { x, y }
|
Self { x, y }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Add for Coord {
|
impl<U: Unit> Add for Coord<U> {
|
||||||
type Output = Coord;
|
type Output = Coord<U>;
|
||||||
|
|
||||||
fn add(self, rhs: Self) -> Self::Output {
|
fn add(self, rhs: Self) -> Self::Output {
|
||||||
Self::new(self.x + rhs.x, self.y + rhs.y)
|
Self::new(self.x + rhs.x, self.y + rhs.y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Add<Direction> for Coord {
|
impl<U: Unit> Sub for Coord<U> {
|
||||||
type Output = Coord;
|
type Output = Coord<U>;
|
||||||
|
|
||||||
|
fn sub(self, rhs: Self) -> Self::Output {
|
||||||
|
Self::new(self.x - rhs.x, self.y - rhs.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<U: Unit> Add<Direction> for Coord<U> {
|
||||||
|
type Output = Coord<U>;
|
||||||
|
|
||||||
fn add(self, rhs: Direction) -> Self::Output {
|
fn add(self, rhs: Direction) -> Self::Output {
|
||||||
let tmp = rhs.lookahead();
|
let tmp = rhs.lookahead();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::ops::{Neg, Not};
|
use std::ops::{Neg, Not};
|
||||||
|
|
||||||
use super::coord::Coord;
|
use super::{coord::Coord, Unit};
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum Direction {
|
pub enum Direction {
|
||||||
|
@ -34,12 +34,12 @@ impl Direction {
|
||||||
*self = !*self
|
*self = !*self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lookahead(&self) -> Coord {
|
pub fn lookahead<U: Unit>(&self) -> Coord<U> {
|
||||||
match self {
|
match self {
|
||||||
Self::Up => Coord::new(0, -1),
|
Self::Up => Coord::new(0.into(), (-1).into()),
|
||||||
Self::Right => Coord::new(1, 0),
|
Self::Right => Coord::new(1.into(), 0.into()),
|
||||||
Self::Down => Coord::new(0, 1),
|
Self::Down => Coord::new(0.into(), 1.into()),
|
||||||
Self::Left => Coord::new(-1, 0),
|
Self::Left => Coord::new((-1).into(), 0.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,3 +11,12 @@ macro_rules! map_solution {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! impl_unit_for_type {
|
||||||
|
($($type:ty),+ $(,)?) => {
|
||||||
|
$(
|
||||||
|
impl $crate::utils::Unit for $type {}
|
||||||
|
)+
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,9 @@ pub mod macros;
|
||||||
pub mod coord;
|
pub mod coord;
|
||||||
pub mod direction;
|
pub mod direction;
|
||||||
|
|
||||||
|
mod unit;
|
||||||
|
pub use unit::*;
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
|
12
src/utils/unit.rs
Normal file
12
src/utils/unit.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
use std::{
|
||||||
|
fmt::Debug,
|
||||||
|
hash::Hash,
|
||||||
|
ops::{Add, Sub},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub trait Unit:
|
||||||
|
Debug + Clone + Copy + PartialEq + Eq + Hash + Add<Output = Self> + Sub<Output = Self> + From<i8>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_unit_for_type!(i8, i16, i32, i64, i128);
|
Loading…
Reference in a new issue