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");
|
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::*;
|
||||||
|
|
|
@ -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 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();
|
||||||
|
|
Loading…
Reference in New Issue