Extract Grid into its own package

This commit is contained in:
Savanni D'Gerinel 2024-12-06 23:09:55 -05:00
parent e86d381098
commit 5f01c48480
3 changed files with 75 additions and 63 deletions

View File

@ -1,3 +1,5 @@
use crate::grid::{Direction, Grid};
const INPUT: &'static str = include_str!("../data/day4.txt"); const INPUT: &'static str = include_str!("../data/day4.txt");
pub fn day4a() -> String { pub fn day4a() -> String {
@ -10,50 +12,6 @@ pub fn day4b() -> String {
format!("{}", find_x_mas(&grid)) format!("{}", find_x_mas(&grid))
} }
struct Grid {
width: usize,
height: usize,
data: Vec<char>,
}
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::<Vec<char>>();
Self {
width,
height,
data,
}
}
}
#[derive(Copy, Clone)]
enum Direction {
East,
SouthEast,
South,
SouthWest,
West,
NorthWest,
North,
NorthEast,
}
fn find_xmas(grid: &Grid) -> usize { fn find_xmas(grid: &Grid) -> usize {
let mut acc = 0; let mut acc = 0;
for x in 0..grid.width { 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() { for c in "XMAS".chars() {
if let Some((cx, cy)) = addr { if let Some((cx, cy)) = addr {
if grid.elem(cx, cy) == c { if grid.elem(cx, cy) == c {
addr = move_pointer(grid, cx, cy, direction); addr = grid.move_pointer(cx, cy, direction);
} else { } else {
return false; return false;
} }
@ -124,10 +82,18 @@ fn check_x_mas(grid: &Grid, x: usize, y: usize) -> bool {
return false; return false;
} }
let nw = move_pointer(&grid, x, y, Direction::NorthWest).map(|(cx, cy)| grid.elem(cx, cy)); let nw = grid
let ne = move_pointer(&grid, x, y, Direction::NorthEast).map(|(cx, cy)| grid.elem(cx, cy)); .move_pointer(x, y, Direction::NorthWest)
let se = move_pointer(&grid, x, y, Direction::SouthEast).map(|(cx, cy)| grid.elem(cx, cy)); .map(|(cx, cy)| grid.elem(cx, cy));
let sw = move_pointer(&grid, x, y, Direction::SouthWest).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) { match (nw, ne, se, sw) {
(Some(nw), Some(ne), Some(se), Some(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)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;

59
2024/src/grid.rs Normal file
View File

@ -0,0 +1,59 @@
pub struct Grid {
pub width: usize,
pub height: usize,
data: Vec<char>,
}
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::<Vec<char>>();
Self {
width,
height,
data,
}
}
}
#[derive(Copy, Clone)]
pub enum Direction {
East,
SouthEast,
South,
SouthWest,
West,
NorthWest,
North,
NorthEast,
}

View File

@ -4,6 +4,7 @@ mod day3;
mod day4; mod day4;
mod day5; mod day5;
mod day6; mod day6;
mod grid;
fn main() { fn main() {
let day = std::env::args().skip(1).next(); let day = std::env::args().skip(1).next();