From 55a073a74797d26758fed4e640954a80ef14dc09 Mon Sep 17 00:00:00 2001 From: Connor Slade Date: Wed, 4 Dec 2024 00:48:29 -0500 Subject: [PATCH] Add ordinal directions to aoc_lib --- aoc_2021/src/day_15.rs | 2 +- aoc_2023/src/day_10.rs | 2 +- aoc_2023/src/day_16.rs | 2 +- aoc_2023/src/day_17.rs | 2 +- aoc_2023/src/day_18.rs | 2 +- aoc_2023/src/day_21.rs | 2 +- aoc_2023/src/day_23.rs | 2 +- aoc_2024/src/day_04.rs | 98 ++++++------------- .../{direction.rs => direction/cardinal.rs} | 0 aoc_lib/src/direction/mod.rs | 2 + aoc_lib/src/direction/ordinal.rs | 47 +++++++++ aoc_lib/src/matrix.rs | 2 +- 12 files changed, 85 insertions(+), 78 deletions(-) rename aoc_lib/src/{direction.rs => direction/cardinal.rs} (100%) create mode 100644 aoc_lib/src/direction/mod.rs create mode 100644 aoc_lib/src/direction/ordinal.rs diff --git a/aoc_2021/src/day_15.rs b/aoc_2021/src/day_15.rs index dd360d3..dde1dfc 100644 --- a/aoc_2021/src/day_15.rs +++ b/aoc_2021/src/day_15.rs @@ -3,7 +3,7 @@ use std::collections::BinaryHeap; use hashbrown::HashMap; use nd_vec::{vector, Vector}; -use aoc_lib::{direction::Direction, matrix::Matrix}; +use aoc_lib::{direction::cardinal::Direction, matrix::Matrix}; use common::{solution, Answer}; solution!("Chiton", 15); diff --git a/aoc_2023/src/day_10.rs b/aoc_2023/src/day_10.rs index c41c2f4..41748c9 100644 --- a/aoc_2023/src/day_10.rs +++ b/aoc_2023/src/day_10.rs @@ -2,7 +2,7 @@ use std::collections::HashSet; use nd_vec::{vector, Vec2}; -use aoc_lib::direction::Direction; +use aoc_lib::direction::cardinal::Direction; use common::{solution, Answer}; type Pos = Vec2; diff --git a/aoc_2023/src/day_16.rs b/aoc_2023/src/day_16.rs index 87ff7f1..cf9ebba 100644 --- a/aoc_2023/src/day_16.rs +++ b/aoc_2023/src/day_16.rs @@ -1,6 +1,6 @@ use std::collections::HashSet; -use aoc_lib::{direction::Direction, matrix::Matrix}; +use aoc_lib::{direction::cardinal::Direction, matrix::Matrix}; use common::{solution, Answer}; use nd_vec::{vector, Vec2}; diff --git a/aoc_2023/src/day_17.rs b/aoc_2023/src/day_17.rs index 8d2c300..5104354 100644 --- a/aoc_2023/src/day_17.rs +++ b/aoc_2023/src/day_17.rs @@ -3,7 +3,7 @@ use std::{ collections::{BinaryHeap, HashMap}, }; -use aoc_lib::{direction::Direction, matrix::Matrix}; +use aoc_lib::{direction::cardinal::Direction, matrix::Matrix}; use common::{solution, Answer}; use nd_vec::{vector, Vec2}; diff --git a/aoc_2023/src/day_18.rs b/aoc_2023/src/day_18.rs index fdbf805..e0d9410 100644 --- a/aoc_2023/src/day_18.rs +++ b/aoc_2023/src/day_18.rs @@ -1,4 +1,4 @@ -use aoc_lib::direction::Direction; +use aoc_lib::direction::cardinal::Direction; use common::{solution, Answer}; use nd_vec::vector; diff --git a/aoc_2023/src/day_21.rs b/aoc_2023/src/day_21.rs index d8765b2..65bd4a5 100644 --- a/aoc_2023/src/day_21.rs +++ b/aoc_2023/src/day_21.rs @@ -1,6 +1,6 @@ use std::collections::HashSet; -use aoc_lib::{direction::Direction, matrix::Matrix}; +use aoc_lib::{direction::cardinal::Direction, matrix::Matrix}; use common::{solution, Answer}; use nd_vec::{vector, Vec2}; diff --git a/aoc_2023/src/day_23.rs b/aoc_2023/src/day_23.rs index 6add1df..3514577 100644 --- a/aoc_2023/src/day_23.rs +++ b/aoc_2023/src/day_23.rs @@ -3,7 +3,7 @@ use std::{ convert::identity, }; -use aoc_lib::{direction::Direction, matrix::Matrix}; +use aoc_lib::{direction::cardinal::Direction, matrix::Matrix}; use common::{solution, Answer}; use nd_vec::{vector, Vec2}; diff --git a/aoc_2024/src/day_04.rs b/aoc_2024/src/day_04.rs index 65335c4..298b9c5 100644 --- a/aoc_2024/src/day_04.rs +++ b/aoc_2024/src/day_04.rs @@ -1,35 +1,35 @@ -use aoc_lib::matrix::Matrix; +use std::convert::identity; + +use aoc_lib::{direction::ordinal::Direction, matrix::Matrix}; use common::{solution, Answer}; -use nd_vec::{vector, Vector}; +use nd_vec::vector; solution!("Ceres Search", 4); fn part_a(input: &str) -> Answer { - let matrix = Matrix::new_chars(input, |x| x); + let matrix = Matrix::new_chars(input, identity); let mut count = 0; for y in 0..matrix.size.y() { for x in 0..matrix.size.x() { let start = vector!(x, y); - for dir in Direction::ALL { - let mut pos = start.clone(); - let mut word = String::new(); - for _ in 0..4 { - if let Some(&chr) = matrix.get(pos) { - word.push(chr); - } else { - break; - } - - let Some(next) = dir.try_advance(pos) else { - break; - }; + if *matrix.get(start).unwrap() != 'X' { + continue; + } + + 'outer: for dir in Direction::ALL { + let mut pos = start; + for expected in ['M', 'A', 'S'] { + let next = dir.try_advance(pos); + let Some(next) = next else { continue 'outer }; pos = next; - } - if word == "XMAS" { - count += 1; + if Some(&expected) != matrix.get(pos) { + continue 'outer; + }; } + + count += 1; } } } @@ -37,8 +37,14 @@ fn part_a(input: &str) -> Answer { count.into() } +/// The directions to advance from the middle 'A' for each MAS instance. +const MAS_DIRECTIONS: [[Direction; 2]; 2] = [ + [Direction::NorthEast, Direction::SouthWest], + [Direction::SouthEast, Direction::NorthWest], +]; + fn part_b(input: &str) -> Answer { - let matrix = Matrix::new_chars(input, |x| x); + let matrix = Matrix::new_chars(input, identity); let mut count = 0; for y in 0..matrix.size.y() { @@ -48,19 +54,10 @@ fn part_b(input: &str) -> Answer { continue; } - let directions = [ - [Direction::NorthEast, Direction::SouthWest], - [Direction::SouthEast, Direction::NorthWest], - // should have a 'M' and a 'S' - ]; - - for mas in directions { + for mas in MAS_DIRECTIONS { let (mut m, mut s) = (false, false); for dir in mas { - let Some(pos) = dir.try_advance(start) else { - continue 'outer; - }; - let Some(&chr) = matrix.get(pos) else { + let Some(&chr) = dir.try_advance(start).and_then(|x| matrix.get(x)) else { continue 'outer; }; @@ -80,45 +77,6 @@ fn part_b(input: &str) -> Answer { count.into() } -#[derive(Debug)] -enum Direction { - North, - NorthEast, - East, - SouthEast, - South, - SouthWest, - West, - NorthWest, -} - -impl Direction { - pub const ALL: [Direction; 8] = [ - Direction::North, - Direction::NorthEast, - Direction::East, - Direction::SouthEast, - Direction::South, - Direction::SouthWest, - Direction::West, - Direction::NorthWest, - ]; - - pub fn try_advance(&self, pos: Vector) -> Option> { - Some(match self { - Self::North => vector!(pos.x(), pos.y() + 1), - Self::NorthEast => vector!(pos.x() + 1, pos.y() + 1), - Self::East => vector!(pos.x() + 1, pos.y()), - Self::SouthEast if pos.y() > 0 => vector!(pos.x() + 1, pos.y() - 1), - Self::South if pos.y() > 0 => vector!(pos.x(), pos.y() - 1), - Self::SouthWest if pos.x() > 0 && pos.y() > 0 => vector!(pos.x() - 1, pos.y() - 1), - Self::West if pos.x() > 0 => vector!(pos.x() - 1, pos.y()), - Self::NorthWest if pos.x() > 0 => vector!(pos.x() - 1, pos.y() + 1), - _ => return None, - }) - } -} - #[cfg(test)] mod test { use indoc::indoc; diff --git a/aoc_lib/src/direction.rs b/aoc_lib/src/direction/cardinal.rs similarity index 100% rename from aoc_lib/src/direction.rs rename to aoc_lib/src/direction/cardinal.rs diff --git a/aoc_lib/src/direction/mod.rs b/aoc_lib/src/direction/mod.rs new file mode 100644 index 0000000..a938233 --- /dev/null +++ b/aoc_lib/src/direction/mod.rs @@ -0,0 +1,2 @@ +pub mod cardinal; +pub mod ordinal; diff --git a/aoc_lib/src/direction/ordinal.rs b/aoc_lib/src/direction/ordinal.rs new file mode 100644 index 0000000..a269e52 --- /dev/null +++ b/aoc_lib/src/direction/ordinal.rs @@ -0,0 +1,47 @@ +use nd_vec::{vector, Vec2}; +use num_traits::Num; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum Direction { + North, + NorthEast, + East, + SouthEast, + South, + SouthWest, + West, + NorthWest, +} + +impl Direction { + pub const ALL: [Direction; 8] = [ + Direction::North, + Direction::NorthEast, + Direction::East, + Direction::SouthEast, + Direction::South, + Direction::SouthWest, + Direction::West, + Direction::NorthWest, + ]; + + pub fn try_advance(&self, pos: Vec2) -> Option> { + Some(match self { + Self::North => vector!(pos.x(), pos.y() + T::one()), + Self::NorthEast => vector!(pos.x() + T::one(), pos.y() + T::one()), + Self::East => vector!(pos.x() + T::one(), pos.y()), + Self::SouthEast if pos.y() > T::zero() => { + vector!(pos.x() + T::one(), pos.y() - T::one()) + } + Self::South if pos.y() > T::zero() => vector!(pos.x(), pos.y() - T::one()), + Self::SouthWest if pos.x() > T::zero() && pos.y() > T::zero() => { + vector!(pos.x() - T::one(), pos.y() - T::one()) + } + Self::West if pos.x() > T::zero() => vector!(pos.x() - T::one(), pos.y()), + Self::NorthWest if pos.x() > T::zero() => { + vector!(pos.x() - T::one(), pos.y() + T::one()) + } + _ => return None, + }) + } +} diff --git a/aoc_lib/src/matrix.rs b/aoc_lib/src/matrix.rs index 2de6d4d..ba20c0e 100644 --- a/aoc_lib/src/matrix.rs +++ b/aoc_lib/src/matrix.rs @@ -21,7 +21,7 @@ impl Matrix { } pub fn new_chars(input: &str, parse: fn(char) -> T) -> Self { - let mut data = Vec::new(); + let mut data = Vec::with_capacity(input.len()); let mut size = vector!(0, 0); for line in input.lines() {