diff --git a/2024/src/day4.rs b/2024/src/day4.rs index 2009f5c..a5bc032 100644 --- a/2024/src/day4.rs +++ b/2024/src/day4.rs @@ -1,3 +1,5 @@ +use crate::grid::{Direction, Grid}; + const INPUT: &'static str = include_str!("../data/day4.txt"); pub fn day4a() -> String { @@ -10,50 +12,6 @@ pub fn day4b() -> String { format!("{}", find_x_mas(&grid)) } -struct Grid { - width: usize, - height: usize, - data: Vec, -} - -impl Grid { - fn elem(&self, x: usize, y: usize) -> char { - if y >= self.height || x >= self.width { - panic!("out of range") - } - self.data[y * self.width + x] - } -} - -impl From<&str> for Grid { - fn from(input: &str) -> Self { - let height = input.lines().count(); - - let first_row = input.lines().next().unwrap(); - let width = first_row.len(); - - let data = input.chars().filter(|c| *c != '\n').collect::>(); - - Self { - width, - height, - data, - } - } -} - -#[derive(Copy, Clone)] -enum Direction { - East, - SouthEast, - South, - SouthWest, - West, - NorthWest, - North, - NorthEast, -} - fn find_xmas(grid: &Grid) -> usize { let mut acc = 0; for x in 0..grid.width { @@ -94,7 +52,7 @@ fn check_xmas(grid: &Grid, x: usize, y: usize, direction: Direction) -> bool { for c in "XMAS".chars() { if let Some((cx, cy)) = addr { if grid.elem(cx, cy) == c { - addr = move_pointer(grid, cx, cy, direction); + addr = grid.move_pointer(cx, cy, direction); } else { return false; } @@ -124,10 +82,18 @@ fn check_x_mas(grid: &Grid, x: usize, y: usize) -> bool { return false; } - let nw = move_pointer(&grid, x, y, Direction::NorthWest).map(|(cx, cy)| grid.elem(cx, cy)); - let ne = move_pointer(&grid, x, y, Direction::NorthEast).map(|(cx, cy)| grid.elem(cx, cy)); - let se = move_pointer(&grid, x, y, Direction::SouthEast).map(|(cx, cy)| grid.elem(cx, cy)); - let sw = move_pointer(&grid, x, y, Direction::SouthWest).map(|(cx, cy)| grid.elem(cx, cy)); + let nw = grid + .move_pointer(x, y, Direction::NorthWest) + .map(|(cx, cy)| grid.elem(cx, cy)); + let ne = grid + .move_pointer(x, y, Direction::NorthEast) + .map(|(cx, cy)| grid.elem(cx, cy)); + let se = grid + .move_pointer(x, y, Direction::SouthEast) + .map(|(cx, cy)| grid.elem(cx, cy)); + let sw = grid + .move_pointer(x, y, Direction::SouthWest) + .map(|(cx, cy)| grid.elem(cx, cy)); match (nw, ne, se, sw) { (Some(nw), Some(ne), Some(se), Some(sw)) => { @@ -165,20 +131,6 @@ fn check_x_mas(grid: &Grid, x: usize, y: usize) -> bool { } } -fn move_pointer(grid: &Grid, x: usize, y: usize, direction: Direction) -> Option<(usize, usize)> { - match direction { - Direction::East if x < grid.width - 1 => Some((x + 1, y)), - Direction::SouthEast if x < grid.width - 1 && y < grid.height - 1 => Some((x + 1, y + 1)), - Direction::South if y < grid.height - 1 => Some((x, y + 1)), - Direction::SouthWest if x > 0 && y < grid.height - 1 => Some((x - 1, y + 1)), - Direction::West if x > 0 => Some((x - 1, y)), - Direction::NorthWest if x > 0 && y > 0 => Some((x - 1, y - 1)), - Direction::North if y > 0 => Some((x, y - 1)), - Direction::NorthEast if x < grid.width - 1 && y > 0 => Some((x + 1, y - 1)), - _ => None, - } -} - #[cfg(test)] mod test { use super::*; diff --git a/2024/src/grid.rs b/2024/src/grid.rs new file mode 100644 index 0000000..ebd19f1 --- /dev/null +++ b/2024/src/grid.rs @@ -0,0 +1,59 @@ +pub struct Grid { + pub width: usize, + pub height: usize, + data: Vec, +} + +impl Grid { + pub fn elem(&self, x: usize, y: usize) -> char { + if y >= self.height || x >= self.width { + panic!("out of range") + } + self.data[y * self.width + x] + } + + pub fn move_pointer(&self, x: usize, y: usize, direction: Direction) -> Option<(usize, usize)> { + match direction { + Direction::East if x < self.width - 1 => Some((x + 1, y)), + Direction::SouthEast if x < self.width - 1 && y < self.height - 1 => { + Some((x + 1, y + 1)) + } + Direction::South if y < self.height - 1 => Some((x, y + 1)), + Direction::SouthWest if x > 0 && y < self.height - 1 => Some((x - 1, y + 1)), + Direction::West if x > 0 => Some((x - 1, y)), + Direction::NorthWest if x > 0 && y > 0 => Some((x - 1, y - 1)), + Direction::North if y > 0 => Some((x, y - 1)), + Direction::NorthEast if x < self.width - 1 && y > 0 => Some((x + 1, y - 1)), + _ => None, + } + } +} + +impl From<&str> for Grid { + fn from(input: &str) -> Self { + let height = input.lines().count(); + + let first_row = input.lines().next().unwrap(); + let width = first_row.len(); + + let data = input.chars().filter(|c| *c != '\n').collect::>(); + + Self { + width, + height, + data, + } + } +} + +#[derive(Copy, Clone)] +pub enum Direction { + East, + SouthEast, + South, + SouthWest, + West, + NorthWest, + North, + NorthEast, +} diff --git a/2024/src/main.rs b/2024/src/main.rs index f33a2d8..3381dea 100644 --- a/2024/src/main.rs +++ b/2024/src/main.rs @@ -4,6 +4,7 @@ mod day3; mod day4; mod day5; mod day6; +mod grid; fn main() { let day = std::env::args().skip(1).next();