Skip to content

Commit

Permalink
d4p2
Browse files Browse the repository at this point in the history
  • Loading branch information
SOF3 committed Dec 7, 2024
1 parent b4f6c23 commit c8c7f80
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 60 deletions.
3 changes: 3 additions & 0 deletions src/all.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,5 +220,8 @@ main! {
part 1 {
"brute" => d4::p1_brute,
}
part 2 {
"brute" => d4::p2_brute,
}
}
}
28 changes: 25 additions & 3 deletions src/all/d4.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::array;

use crate::util::{DirectDiagonal, GridView};
use crate::util::{Direct, DirectBoth, DirectDiagonal, GridView};

pub fn p1_brute(input: String) -> u32 {
let grid = GridView::new(&input);
Expand All @@ -9,9 +9,9 @@ pub fn p1_brute(input: String) -> u32 {

for (index, _) in input.match_indices('X') {
let loc = grid.index_to_loc(index).unwrap();
for dir in DirectDiagonal::ALL {
for &dir in DirectBoth::ALL {
let mut iter =
loc.direct_diagonal_iter(dir, grid).skip(1).take(3).map(|loc| grid.get(loc));
loc.direct_iter(dir, grid).skip(1).take(3).map(|loc| grid.get(loc));
let chars: [_; 3] = array::from_fn(|_| iter.next().flatten());
if chars == [Some(b'M'), Some(b'A'), Some(b'S')] {
count += 1;
Expand All @@ -21,3 +21,25 @@ pub fn p1_brute(input: String) -> u32 {

count
}

pub fn p2_brute(input: String) -> u32 {
let grid = GridView::new(&input);

let mut count = 0;

for (index, _) in input.match_indices('A') {
let loc = grid.index_to_loc(index).unwrap();
let matched = [
[DirectDiagonal::LeftUp, DirectDiagonal::RightDown],
[DirectDiagonal::RightUp, DirectDiagonal::LeftDown],
].map(|ends| {
let values = ends .map(|direct| grid.get(loc.direct(direct, grid)?));
values == [Some(b'M'), Some(b'S')] || values == [Some(b'S'), Some(b'M')]
});
if matched[0] && matched[1] {
count += 1;
}
}

count
}
132 changes: 75 additions & 57 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,16 @@ use std::iter;

#[derive(Clone, Copy)]
pub struct GridView<'a> {
input: &'a [u8],
width: u32,
input: &'a [u8],
width: u32,
height: u32,
}

impl<'a> GridView<'a> {
pub fn new(input: &'a impl AsRef<[u8]>) -> Self {
let input = input.as_ref();
let width= input.iter().position(|&b| b == b'\n').unwrap() as u32+1;
Self {
input,
width,
height: (input.len() as u32).div_ceil(width),
}
let width = input.iter().position(|&b| b == b'\n').unwrap() as u32 + 1;
Self { input, width, height: (input.len() as u32).div_ceil(width) }
}

pub fn get(&self, loc: GridLoc) -> Option<u8> {
Expand All @@ -42,12 +38,7 @@ pub struct GridLoc {
}

impl GridLoc {
pub fn left(self) -> Option<Self> {
Some(Self {
x: self.x.checked_sub(1)?,
y: self.y,
})
}
pub fn left(self) -> Option<Self> { Some(Self { x: self.x.checked_sub(1)?, y: self.y }) }
pub fn right(self, grid: GridView) -> Option<Self> {
Some(Self {
x: match self.x.checked_add(1)? {
Expand All @@ -57,12 +48,7 @@ impl GridLoc {
y: self.y,
})
}
pub fn up(self) -> Option<Self> {
Some(Self {
x: self.x,
y: self.y.checked_sub(1)?,
})
}
pub fn up(self) -> Option<Self> { Some(Self { x: self.x, y: self.y.checked_sub(1)? }) }
pub fn down(self, grid: GridView) -> Option<Self> {
Some(Self {
x: self.x,
Expand All @@ -73,61 +59,53 @@ impl GridLoc {
})
}

pub fn direct(self, direct: Direct, grid: GridView) -> Option<Self> {
match direct {
Direct::Left => self.left(),
Direct::Right => self.right(grid),
Direct::Up => self.up(),
Direct::Down => self.down(grid),
}
pub fn direct(self, direct: impl Direct, grid: GridView) -> Option<Self> {
direct.apply(self, grid)
}

pub fn direct_diagonal(self, direct: DirectDiagonal, grid: GridView) -> Option<Self> {
match direct {
DirectDiagonal::Left => self.left(),
DirectDiagonal::Right => self.right(grid),
DirectDiagonal::Up => self.up(),
DirectDiagonal::Down => self.down(grid),
DirectDiagonal::LeftUp => self.left().and_then(Self::up),
DirectDiagonal::RightUp => self.right(grid).and_then(Self::up),
DirectDiagonal::LeftDown => self.left().and_then(|loc| loc.down(grid)),
DirectDiagonal::RightDown => self.right(grid).and_then(|loc| loc.down(grid)),
}
}

fn direct_any_iter<F>(self, mutate: F, grid: GridView) -> impl Iterator<Item = Self> + use<'_, F>
where F: Fn(GridLoc, GridView) -> Option<GridLoc>{
pub fn direct_iter<D: Direct>(
self,
direct: D,
grid: GridView,
) -> impl Iterator<Item = Self> + use<'_, D> {
let mut loc = Some(self);
iter::from_fn(move || {
let output = loc?;
loc = mutate(output, grid);
loc = direct.apply(output, grid);
Some(output)
})
}
}

pub fn direct_iter(self, direct: Direct, grid: GridView) -> impl Iterator<Item = Self> + use<'_> {
self.direct_any_iter(move |loc, grid| loc.direct(direct, grid), grid)
}
pub trait Direct: Copy + 'static {
const ALL: &[Self];

pub fn direct_diagonal_iter(self, direct: DirectDiagonal, grid: GridView) -> impl Iterator<Item = Self> + use<'_> {
self.direct_any_iter(move |loc, grid| loc.direct_diagonal(direct, grid), grid)
}
fn apply(self, loc: GridLoc, grid: GridView) -> Option<GridLoc>;
}

#[derive(Debug, Clone, Copy)]
pub enum Direct {
pub enum DirectTaxicab {
Left,
Right,
Up,
Down,
}

impl Direct {
pub const ALL: [Self; 4] = [Self::Left, Self::Right, Self::Up, Self::Down];
impl Direct for DirectTaxicab {
const ALL: &[Self] = &[Self::Left, Self::Right, Self::Up, Self::Down];

fn apply(self, loc: GridLoc, grid: GridView) -> Option<GridLoc> {
match self {
Self::Left => loc.left(),
Self::Right => loc.right(grid),
Self::Up => loc.up(),
Self::Down => loc.down(grid),
}
}
}

#[derive(Debug, Clone, Copy)]
pub enum DirectDiagonal {
pub enum DirectBoth {
Left,
Right,
Up,
Expand All @@ -138,9 +116,49 @@ pub enum DirectDiagonal {
RightDown,
}

impl DirectDiagonal {
pub const ALL: [Self; 8] = [
Self::Left, Self::Right, Self::Up, Self::Down,
Self::LeftUp, Self::RightUp, Self::LeftDown, Self::RightDown,
impl Direct for DirectBoth {
const ALL: &[Self] = &[
Self::Left,
Self::Right,
Self::Up,
Self::Down,
Self::LeftUp,
Self::RightUp,
Self::LeftDown,
Self::RightDown,
];

fn apply(self, loc: GridLoc, grid: GridView) -> Option<GridLoc> {
match self {
Self::Left => loc.left(),
Self::Right => loc.right(grid),
Self::Up => loc.up(),
Self::Down => loc.down(grid),
Self::LeftUp => loc.left().and_then(GridLoc::up),
Self::RightUp => loc.right(grid).and_then(GridLoc::up),
Self::LeftDown => loc.left().and_then(|loc2| loc2.down(grid)),
Self::RightDown => loc.right(grid).and_then(|loc2| loc2.down(grid)),
}
}
}

#[derive(Debug, Clone, Copy)]
pub enum DirectDiagonal {
LeftUp,
RightUp,
LeftDown,
RightDown,
}

impl Direct for DirectDiagonal {
const ALL: &[Self] = &[Self::LeftUp, Self::RightUp, Self::LeftDown, Self::RightDown];

fn apply(self, loc: GridLoc, grid: GridView) -> Option<GridLoc> {
match self {
Self::LeftUp => loc.left().and_then(GridLoc::up),
Self::RightUp => loc.right(grid).and_then(GridLoc::up),
Self::LeftDown => loc.left().and_then(|loc2| loc2.down(grid)),
Self::RightDown => loc.right(grid).and_then(|loc2| loc2.down(grid)),
}
}
}

0 comments on commit c8c7f80

Please sign in to comment.