finish day8 and refactor

This commit is contained in:
JasterV 2025-03-31 23:35:30 +02:00
parent 68f6a8e6f7
commit c081936a7d
6 changed files with 65 additions and 53 deletions

View file

@ -27,6 +27,7 @@ library
exposed-modules:
Data.List.Extra
Data.Matrix
Data.Point
Day1
Day2
Day3

View file

@ -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

18
src/Data/Point.hs Normal file
View file

@ -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)

View file

@ -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 =

View file

@ -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

View file

@ -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
getAntiNodes x y =
case P.distance x y of
(0, 0) -> []
d -> computePointsAtDistance x d add ++ computePointsAtDistance y d substract
d -> [P.add x d, P.substract y d]
computePointsAtDistance point dist f =
let point' = f point dist
partTwo :: String -> Int
partTwo input = length (nub antiNodes)
where
matrix = M.buildMatrix (lines input)
pairs = pairNodes matrix
antiNodes = concatMap (uncurry getAntiNodes) pairs
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 : computePointsAtDistance point' dist f
then point : go point' distance f
else []
nodePairs :: Matrix Char -> [(Node, Node)]
nodePairs matrix =
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