This commit is contained in:
Rh4096 2024-12-08 21:55:00 +07:00
parent a3f3964e96
commit 9c53f28588
12 changed files with 164 additions and 29 deletions

16
Cargo.lock generated
View file

@ -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"

View file

@ -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"

View file

@ -29,6 +29,7 @@ fn main() -> Result<()> {
5 => AocDayFiveSolution, 5 => AocDayFiveSolution,
6 => AocDaySixSolution, 6 => AocDaySixSolution,
7 => AocDaySevenSolution, 7 => AocDaySevenSolution,
8 => AocDayEightSolution,
}; };
Ok(()) Ok(())

View file

@ -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));

View file

@ -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 {

View file

@ -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;

View file

@ -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())
} }
} }

View file

@ -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();

View file

@ -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()),
} }
} }
} }

View file

@ -11,3 +11,12 @@ macro_rules! map_solution {
} }
}; };
} }
#[macro_export]
macro_rules! impl_unit_for_type {
($($type:ty),+ $(,)?) => {
$(
impl $crate::utils::Unit for $type {}
)+
};
}

View file

@ -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
View 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);