From c081936a7d127baf9c3bf8747770c6917ea6ad3b Mon Sep 17 00:00:00 2001 From: JasterV <49537445+JasterV@users.noreply.github.com> Date: Mon, 31 Mar 2025 23:35:30 +0200 Subject: [PATCH] finish day8 and refactor --- aoc2024.cabal | 1 + src/Data/Matrix.hs | 18 ++++++------ src/Data/Point.hs | 18 ++++++++++++ src/Day6.hs | 9 +++--- src/Day6/Guard.hs | 4 +-- src/Day8.hs | 68 +++++++++++++++++++++------------------------- 6 files changed, 65 insertions(+), 53 deletions(-) create mode 100644 src/Data/Point.hs diff --git a/aoc2024.cabal b/aoc2024.cabal index 0e71389..628fde5 100644 --- a/aoc2024.cabal +++ b/aoc2024.cabal @@ -27,6 +27,7 @@ library exposed-modules: Data.List.Extra Data.Matrix + Data.Point Day1 Day2 Day3 diff --git a/src/Data/Matrix.hs b/src/Data/Matrix.hs index a657bd6..f0328f7 100644 --- a/src/Data/Matrix.hs +++ b/src/Data/Matrix.hs @@ -3,7 +3,6 @@ module Data.Matrix ( Matrix, - Position, buildMatrix, lookupValue, lookup, @@ -21,12 +20,11 @@ import Data.List (find) import Data.Map.Lazy (Map) import qualified Data.Map.Lazy as Map import Data.Maybe +import Data.Point (Point) import Prelude hiding (filter, lookup) newtype Matrix v = Matrix (Map (Int, Int) v) -type Position = (Int, Int) - buildMatrix :: [[a]] -> Matrix a buildMatrix xs = Matrix (go xs 0 Map.empty) where @@ -43,22 +41,22 @@ buildMatrix xs = Matrix (go xs 0 Map.empty) size :: Matrix v -> Int size (Matrix hmap) = Map.size hmap -isInBounds :: Position -> Matrix v -> Bool +isInBounds :: Point -> Matrix v -> Bool isInBounds pos (Matrix hmap) = Map.member pos hmap -filterWithKey :: (Position -> v -> Bool) -> Matrix v -> Matrix v +filterWithKey :: (Point -> v -> Bool) -> Matrix v -> Matrix v filterWithKey f (Matrix hmap) = Matrix (Map.filterWithKey f hmap) filter :: (v -> Bool) -> Matrix v -> Matrix v filter f (Matrix hmap) = Matrix (Map.filter f hmap) -lookup :: Position -> Matrix v -> Maybe v +lookup :: Point -> Matrix v -> Maybe v lookup position (Matrix hmap) = Map.lookup position hmap -lookupMultiple :: [Position] -> Matrix v -> [v] +lookupMultiple :: [Point] -> Matrix v -> [v] lookupMultiple positions matrix = mapMaybe (`lookup` matrix) positions -insert :: Position -> v -> Matrix v -> Matrix v +insert :: Point -> v -> Matrix v -> Matrix v insert position value (Matrix hmap) = Matrix $ if Map.member position hmap @@ -69,7 +67,7 @@ insert position value (Matrix hmap) = Search for the given value on the matrix. Return the position of the first match if found and nothing if it doens't exist. --} -lookupValue :: (Eq v) => v -> Matrix v -> Maybe Position +lookupValue :: (Eq v) => v -> Matrix v -> Maybe Point lookupValue v (Matrix hmap) = let entries = Map.toAscList hmap mEntry = find ((== v) . snd) entries @@ -80,7 +78,7 @@ Group elements given a function. The function receives an entry of the matrix and returns a pair of key -> value. The values are grouped in order. --} -groupByWith :: forall v a b. (Ord a) => ((Position, v) -> (a, b)) -> Matrix v -> Map a [b] +groupByWith :: forall v a b. (Ord a) => ((Point, v) -> (a, b)) -> Matrix v -> Map a [b] groupByWith f (Matrix hmap) = let sortedEntries = Map.toAscList hmap in foldr (insert' . f) Map.empty sortedEntries diff --git a/src/Data/Point.hs b/src/Data/Point.hs new file mode 100644 index 0000000..028e1e8 --- /dev/null +++ b/src/Data/Point.hs @@ -0,0 +1,18 @@ +module Data.Point + ( Point, + substract, + add, + distance, + ) +where + +type Point = (Int, Int) + +substract :: Point -> (Int, Int) -> (Int, Int) +substract (x, y) (dx, dy) = (x - dx, y - dy) + +add :: Point -> (Int, Int) -> (Int, Int) +add (x, y) (dx, dy) = (x + dx, y + dy) + +distance :: Point -> Point -> (Int, Int) +distance (xrow, xcol) (yrow, ycol) = (xrow - yrow, xcol - ycol) diff --git a/src/Day6.hs b/src/Day6.hs index 6805e24..6ed86a1 100644 --- a/src/Day6.hs +++ b/src/Day6.hs @@ -1,8 +1,9 @@ module Day6 (partOne, partTwo) where import qualified Data.HashSet as HashSet -import Data.Matrix (Matrix, Position) +import Data.Matrix (Matrix) import qualified Data.Matrix as M +import Data.Point (Point) import Day6.Guard (Guard (..)) import qualified Day6.Guard as G @@ -21,8 +22,8 @@ partTwo input = do let labMap = parseLabMap input guard <- findGuard labMap route <- predictGuardsRoute guard labMap - let initialPosition = position guard - candidates = filter (/= initialPosition) route + let initialPoint = position guard + candidates = filter (/= initialPoint) route return $ length $ @@ -52,7 +53,7 @@ findGuard matrix = [_, _, _, Just pos] -> Right (Guard pos G.Left) _ -> Left GuardNotFoundError -predictGuardsRoute :: Guard -> LabMap -> Either Error [Position] +predictGuardsRoute :: Guard -> LabMap -> Either Error [Point] predictGuardsRoute initialGuard labMap = go initialGuard HashSet.empty HashSet.empty where go guard visited acc = diff --git a/src/Day6/Guard.hs b/src/Day6/Guard.hs index 7276a45..0377985 100644 --- a/src/Day6/Guard.hs +++ b/src/Day6/Guard.hs @@ -3,7 +3,7 @@ module Day6.Guard (Guard (..), Direction (..), moveForward, turnRight) where import Data.Hashable -import Data.Matrix (Position) +import Data.Point (Point) import GHC.Generics (Generic) import Prelude hiding (Left, Right) @@ -12,7 +12,7 @@ data Direction = Up | Down | Left | Right instance Hashable Direction -data Guard = Guard {position :: Position, directon :: Direction} +data Guard = Guard {position :: Point, directon :: Direction} deriving (Eq, Generic) instance Hashable Guard diff --git a/src/Day8.hs b/src/Day8.hs index 2c8d3d5..0089496 100644 --- a/src/Day8.hs +++ b/src/Day8.hs @@ -1,51 +1,45 @@ module Day8 (partOne, partTwo) where import Data.List (nub) -import Data.List.Extra (pairs) +import qualified Data.List.Extra as LE import qualified Data.Map.Lazy as Map -import Data.Matrix (Matrix, Position) +import Data.Matrix (Matrix) import qualified Data.Matrix as M - -type Node = (Int, Int) +import Data.Point (Point) +import qualified Data.Point as P partOne :: String -> Int -partOne input = length $ filter (`M.isInBounds` grid) $ nub antiNodes - where - grid = M.buildMatrix (lines input) - antiNodes = concatMap (uncurry getAntiNodes) $ nodePairs grid - - getAntiNodes x y = case distance x y of - (0, 0) -> [] - d -> [add x d, substract y d] - -partTwo :: String -> Int -partTwo input = length antiNodes +partOne input = length $ filter (`M.isInBounds` matrix) $ nub antiNodes where matrix = M.buildMatrix (lines input) - combinations = nodePairs matrix - antiNodes = nub $ concatMap (uncurry getAntiNodes) combinations + pairs = pairNodes matrix + antiNodes = concatMap (uncurry getAntiNodes) pairs - getAntiNodes x y = case distance x y of - (0, 0) -> [] - d -> computePointsAtDistance x d add ++ computePointsAtDistance y d substract + getAntiNodes x y = + case P.distance x y of + (0, 0) -> [] + d -> [P.add x d, P.substract y d] - computePointsAtDistance point dist f = - let point' = f point dist - in if M.isInBounds point matrix - then point : computePointsAtDistance point' dist f - else [] +partTwo :: String -> Int +partTwo input = length (nub antiNodes) + where + matrix = M.buildMatrix (lines input) + pairs = pairNodes matrix + antiNodes = concatMap (uncurry getAntiNodes) pairs -nodePairs :: Matrix Char -> [(Node, Node)] -nodePairs matrix = + getAntiNodes x y = + let distance = P.distance x y + in go x distance P.add ++ go y distance P.substract + where + go _ (0, 0) _ = [] + go point distance f = + let point' = f point distance + in if M.isInBounds point matrix + then point : go point' distance f + else [] + +pairNodes :: Matrix Char -> [(Point, Point)] +pairNodes matrix = let noDotsMatrix = M.filter (/= '.') matrix pointGroups = Map.elems $ M.groupByWith (\(position, value) -> (value, position)) noDotsMatrix - in concatMap pairs pointGroups - -substract :: Position -> (Int, Int) -> (Int, Int) -substract (x, y) (dx, dy) = (x - dx, y - dy) - -add :: Position -> (Int, Int) -> (Int, Int) -add (x, y) (dx, dy) = (x + dx, y + dy) - -distance :: Position -> Position -> (Int, Int) -distance (xrow, xcol) (yrow, ycol) = (xrow - yrow, xcol - ycol) + in concatMap LE.pairs pointGroups