Extract Grid into its own package
This commit is contained in:
parent
e86d381098
commit
5f01c48480
|
@ -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<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 {
|
||||
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::*;
|
||||
|
|
|
@ -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,
|
||||
}
|
|
@ -4,6 +4,7 @@ mod day3;
|
|||
mod day4;
|
||||
mod day5;
|
||||
mod day6;
|
||||
mod grid;
|
||||
|
||||
fn main() {
|
||||
let day = std::env::args().skip(1).next();
|
||||
|
|
Loading…
Reference in New Issue