From c8c7f80ab3a5cd3bb7e82065d91b908f96f793e1 Mon Sep 17 00:00:00 2001 From: SOFe Date: Sat, 7 Dec 2024 17:00:31 +0800 Subject: [PATCH] d4p2 --- src/all.rs | 3 ++ src/all/d4.rs | 28 +++++++++-- src/util.rs | 132 ++++++++++++++++++++++++++++---------------------- 3 files changed, 103 insertions(+), 60 deletions(-) diff --git a/src/all.rs b/src/all.rs index ab092b7..bee8d30 100644 --- a/src/all.rs +++ b/src/all.rs @@ -220,5 +220,8 @@ main! { part 1 { "brute" => d4::p1_brute, } + part 2 { + "brute" => d4::p2_brute, + } } } diff --git a/src/all/d4.rs b/src/all/d4.rs index 77cd227..23953bd 100644 --- a/src/all/d4.rs +++ b/src/all/d4.rs @@ -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); @@ -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; @@ -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 +} diff --git a/src/util.rs b/src/util.rs index 7d7c3fa..deacb05 100644 --- a/src/util.rs +++ b/src/util.rs @@ -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 { @@ -42,12 +38,7 @@ pub struct GridLoc { } impl GridLoc { - pub fn left(self) -> Option { - Some(Self { - x: self.x.checked_sub(1)?, - y: self.y, - }) - } + pub fn left(self) -> Option { Some(Self { x: self.x.checked_sub(1)?, y: self.y }) } pub fn right(self, grid: GridView) -> Option { Some(Self { x: match self.x.checked_add(1)? { @@ -57,12 +48,7 @@ impl GridLoc { y: self.y, }) } - pub fn up(self) -> Option { - Some(Self { - x: self.x, - y: self.y.checked_sub(1)?, - }) - } + pub fn up(self) -> Option { Some(Self { x: self.x, y: self.y.checked_sub(1)? }) } pub fn down(self, grid: GridView) -> Option { Some(Self { x: self.x, @@ -73,61 +59,53 @@ impl GridLoc { }) } - pub fn direct(self, direct: Direct, grid: GridView) -> Option { - 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 { + direct.apply(self, grid) } - pub fn direct_diagonal(self, direct: DirectDiagonal, grid: GridView) -> Option { - 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(self, mutate: F, grid: GridView) -> impl Iterator + use<'_, F> - where F: Fn(GridLoc, GridView) -> Option{ + pub fn direct_iter( + self, + direct: D, + grid: GridView, + ) -> impl Iterator + 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 + 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 + use<'_> { - self.direct_any_iter(move |loc, grid| loc.direct_diagonal(direct, grid), grid) - } + fn apply(self, loc: GridLoc, grid: GridView) -> Option; } #[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 { + 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, @@ -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 { + 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 { + 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)), + } + } }