mirror of
https://codeberg.org/JasterV/aoc2024-haskell.git
synced 2026-04-26 18:10:05 +00:00
finish day8 and refactor
This commit is contained in:
parent
68f6a8e6f7
commit
c081936a7d
6 changed files with 65 additions and 53 deletions
|
|
@ -27,6 +27,7 @@ library
|
||||||
exposed-modules:
|
exposed-modules:
|
||||||
Data.List.Extra
|
Data.List.Extra
|
||||||
Data.Matrix
|
Data.Matrix
|
||||||
|
Data.Point
|
||||||
Day1
|
Day1
|
||||||
Day2
|
Day2
|
||||||
Day3
|
Day3
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
module Data.Matrix
|
module Data.Matrix
|
||||||
( Matrix,
|
( Matrix,
|
||||||
Position,
|
|
||||||
buildMatrix,
|
buildMatrix,
|
||||||
lookupValue,
|
lookupValue,
|
||||||
lookup,
|
lookup,
|
||||||
|
|
@ -21,12 +20,11 @@ import Data.List (find)
|
||||||
import Data.Map.Lazy (Map)
|
import Data.Map.Lazy (Map)
|
||||||
import qualified Data.Map.Lazy as Map
|
import qualified Data.Map.Lazy as Map
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
|
import Data.Point (Point)
|
||||||
import Prelude hiding (filter, lookup)
|
import Prelude hiding (filter, lookup)
|
||||||
|
|
||||||
newtype Matrix v = Matrix (Map (Int, Int) v)
|
newtype Matrix v = Matrix (Map (Int, Int) v)
|
||||||
|
|
||||||
type Position = (Int, Int)
|
|
||||||
|
|
||||||
buildMatrix :: [[a]] -> Matrix a
|
buildMatrix :: [[a]] -> Matrix a
|
||||||
buildMatrix xs = Matrix (go xs 0 Map.empty)
|
buildMatrix xs = Matrix (go xs 0 Map.empty)
|
||||||
where
|
where
|
||||||
|
|
@ -43,22 +41,22 @@ buildMatrix xs = Matrix (go xs 0 Map.empty)
|
||||||
size :: Matrix v -> Int
|
size :: Matrix v -> Int
|
||||||
size (Matrix hmap) = Map.size hmap
|
size (Matrix hmap) = Map.size hmap
|
||||||
|
|
||||||
isInBounds :: Position -> Matrix v -> Bool
|
isInBounds :: Point -> Matrix v -> Bool
|
||||||
isInBounds pos (Matrix hmap) = Map.member pos hmap
|
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)
|
filterWithKey f (Matrix hmap) = Matrix (Map.filterWithKey f hmap)
|
||||||
|
|
||||||
filter :: (v -> Bool) -> Matrix v -> Matrix v
|
filter :: (v -> Bool) -> Matrix v -> Matrix v
|
||||||
filter f (Matrix hmap) = Matrix (Map.filter f hmap)
|
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
|
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
|
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) =
|
insert position value (Matrix hmap) =
|
||||||
Matrix $
|
Matrix $
|
||||||
if Map.member position hmap
|
if Map.member position hmap
|
||||||
|
|
@ -69,7 +67,7 @@ insert position value (Matrix hmap) =
|
||||||
Search for the given value on the matrix.
|
Search for the given value on the matrix.
|
||||||
Return the position of the first match if found and nothing if it doens't exist.
|
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) =
|
lookupValue v (Matrix hmap) =
|
||||||
let entries = Map.toAscList hmap
|
let entries = Map.toAscList hmap
|
||||||
mEntry = find ((== v) . snd) entries
|
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 function receives an entry of the matrix and returns a pair of key -> value.
|
||||||
The values are grouped in order.
|
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) =
|
groupByWith f (Matrix hmap) =
|
||||||
let sortedEntries = Map.toAscList hmap
|
let sortedEntries = Map.toAscList hmap
|
||||||
in foldr (insert' . f) Map.empty sortedEntries
|
in foldr (insert' . f) Map.empty sortedEntries
|
||||||
|
|
|
||||||
18
src/Data/Point.hs
Normal file
18
src/Data/Point.hs
Normal 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)
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
module Day6 (partOne, partTwo) where
|
module Day6 (partOne, partTwo) where
|
||||||
|
|
||||||
import qualified Data.HashSet as HashSet
|
import qualified Data.HashSet as HashSet
|
||||||
import Data.Matrix (Matrix, Position)
|
import Data.Matrix (Matrix)
|
||||||
import qualified Data.Matrix as M
|
import qualified Data.Matrix as M
|
||||||
|
import Data.Point (Point)
|
||||||
import Day6.Guard (Guard (..))
|
import Day6.Guard (Guard (..))
|
||||||
import qualified Day6.Guard as G
|
import qualified Day6.Guard as G
|
||||||
|
|
||||||
|
|
@ -21,8 +22,8 @@ partTwo input = do
|
||||||
let labMap = parseLabMap input
|
let labMap = parseLabMap input
|
||||||
guard <- findGuard labMap
|
guard <- findGuard labMap
|
||||||
route <- predictGuardsRoute guard labMap
|
route <- predictGuardsRoute guard labMap
|
||||||
let initialPosition = position guard
|
let initialPoint = position guard
|
||||||
candidates = filter (/= initialPosition) route
|
candidates = filter (/= initialPoint) route
|
||||||
|
|
||||||
return $
|
return $
|
||||||
length $
|
length $
|
||||||
|
|
@ -52,7 +53,7 @@ findGuard matrix =
|
||||||
[_, _, _, Just pos] -> Right (Guard pos G.Left)
|
[_, _, _, Just pos] -> Right (Guard pos G.Left)
|
||||||
_ -> Left GuardNotFoundError
|
_ -> Left GuardNotFoundError
|
||||||
|
|
||||||
predictGuardsRoute :: Guard -> LabMap -> Either Error [Position]
|
predictGuardsRoute :: Guard -> LabMap -> Either Error [Point]
|
||||||
predictGuardsRoute initialGuard labMap = go initialGuard HashSet.empty HashSet.empty
|
predictGuardsRoute initialGuard labMap = go initialGuard HashSet.empty HashSet.empty
|
||||||
where
|
where
|
||||||
go guard visited acc =
|
go guard visited acc =
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
module Day6.Guard (Guard (..), Direction (..), moveForward, turnRight) where
|
module Day6.Guard (Guard (..), Direction (..), moveForward, turnRight) where
|
||||||
|
|
||||||
import Data.Hashable
|
import Data.Hashable
|
||||||
import Data.Matrix (Position)
|
import Data.Point (Point)
|
||||||
import GHC.Generics (Generic)
|
import GHC.Generics (Generic)
|
||||||
import Prelude hiding (Left, Right)
|
import Prelude hiding (Left, Right)
|
||||||
|
|
||||||
|
|
@ -12,7 +12,7 @@ data Direction = Up | Down | Left | Right
|
||||||
|
|
||||||
instance Hashable Direction
|
instance Hashable Direction
|
||||||
|
|
||||||
data Guard = Guard {position :: Position, directon :: Direction}
|
data Guard = Guard {position :: Point, directon :: Direction}
|
||||||
deriving (Eq, Generic)
|
deriving (Eq, Generic)
|
||||||
|
|
||||||
instance Hashable Guard
|
instance Hashable Guard
|
||||||
|
|
|
||||||
68
src/Day8.hs
68
src/Day8.hs
|
|
@ -1,51 +1,45 @@
|
||||||
module Day8 (partOne, partTwo) where
|
module Day8 (partOne, partTwo) where
|
||||||
|
|
||||||
import Data.List (nub)
|
import Data.List (nub)
|
||||||
import Data.List.Extra (pairs)
|
import qualified Data.List.Extra as LE
|
||||||
import qualified Data.Map.Lazy as Map
|
import qualified Data.Map.Lazy as Map
|
||||||
import Data.Matrix (Matrix, Position)
|
import Data.Matrix (Matrix)
|
||||||
import qualified Data.Matrix as M
|
import qualified Data.Matrix as M
|
||||||
|
import Data.Point (Point)
|
||||||
type Node = (Int, Int)
|
import qualified Data.Point as P
|
||||||
|
|
||||||
partOne :: String -> Int
|
partOne :: String -> Int
|
||||||
partOne input = length $ filter (`M.isInBounds` grid) $ nub antiNodes
|
partOne input = length $ filter (`M.isInBounds` matrix) $ 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
|
|
||||||
where
|
where
|
||||||
matrix = M.buildMatrix (lines input)
|
matrix = M.buildMatrix (lines input)
|
||||||
combinations = nodePairs matrix
|
pairs = pairNodes matrix
|
||||||
antiNodes = nub $ concatMap (uncurry getAntiNodes) combinations
|
antiNodes = concatMap (uncurry getAntiNodes) pairs
|
||||||
|
|
||||||
getAntiNodes x y = case distance x y of
|
getAntiNodes x y =
|
||||||
(0, 0) -> []
|
case P.distance x y of
|
||||||
d -> computePointsAtDistance x d add ++ computePointsAtDistance y d substract
|
(0, 0) -> []
|
||||||
|
d -> [P.add x d, P.substract y d]
|
||||||
|
|
||||||
computePointsAtDistance point dist f =
|
partTwo :: String -> Int
|
||||||
let point' = f point dist
|
partTwo input = length (nub antiNodes)
|
||||||
in if M.isInBounds point matrix
|
where
|
||||||
then point : computePointsAtDistance point' dist f
|
matrix = M.buildMatrix (lines input)
|
||||||
else []
|
pairs = pairNodes matrix
|
||||||
|
antiNodes = concatMap (uncurry getAntiNodes) pairs
|
||||||
|
|
||||||
nodePairs :: Matrix Char -> [(Node, Node)]
|
getAntiNodes x y =
|
||||||
nodePairs matrix =
|
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
|
let noDotsMatrix = M.filter (/= '.') matrix
|
||||||
pointGroups = Map.elems $ M.groupByWith (\(position, value) -> (value, position)) noDotsMatrix
|
pointGroups = Map.elems $ M.groupByWith (\(position, value) -> (value, position)) noDotsMatrix
|
||||||
in concatMap pairs pointGroups
|
in concatMap LE.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)
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue