This commit is contained in:
JasterV 2025-03-31 23:16:11 +02:00
parent a65720daaf
commit 68f6a8e6f7
4 changed files with 82 additions and 22 deletions

View file

@ -25,6 +25,7 @@ source-repository head
library library
exposed-modules: exposed-modules:
Data.List.Extra
Data.Matrix Data.Matrix
Day1 Day1
Day2 Day2
@ -62,6 +63,7 @@ test-suite aoc2024-test
Day5Spec Day5Spec
Day6Spec Day6Spec
Day7Spec Day7Spec
Day8Spec
Paths_aoc2024 Paths_aoc2024
autogen-modules: autogen-modules:
Paths_aoc2024 Paths_aoc2024

14
src/Data/List/Extra.hs Normal file
View file

@ -0,0 +1,14 @@
module Data.List.Extra (combinations, pairs) where
import Data.List (subsequences)
import Data.Maybe (mapMaybe)
combinations :: Int -> [a] -> [[a]]
combinations k xs = filter ((== k) . length) $ subsequences xs
pairs :: [a] -> [(a, a)]
pairs xs = mapMaybe parse $ combinations 2 xs
where
parse :: [a] -> Maybe (a, a)
parse [x, y] = Just (x, y)
parse _ = Nothing

View file

@ -1,34 +1,51 @@
module Day8 (partOne, partTwo) where module Day8 (partOne, partTwo) where
import Data.List (nub, subsequences) import Data.List (nub)
import Data.List.Extra (pairs)
import qualified Data.Map.Lazy as Map import qualified Data.Map.Lazy as Map
import Data.Matrix (Position) import Data.Matrix (Matrix, Position)
import qualified Data.Matrix as M import qualified Data.Matrix as M
import Data.Maybe (mapMaybe)
type AntiNode = (Int, Int) type Node = (Int, Int)
partOne :: String -> Int partOne :: String -> Int
partOne input = length $ filter (`M.isInBounds` matrix) $ nub $ concatMap (uncurry getAntiNodes) combinations partOne input = length $ filter (`M.isInBounds` grid) $ nub antiNodes
where where
matrix = M.buildMatrix (lines input) grid = M.buildMatrix (lines input)
noDotsMatrix = M.filter (/= '.') matrix antiNodes = concatMap (uncurry getAntiNodes) $ nodePairs grid
pointGroups = Map.elems $ M.groupByWith (\(position, value) -> (value, position)) noDotsMatrix
combinations = concatMap pairs pointGroups getAntiNodes x y = case distance x y of
(0, 0) -> []
d -> [add x d, substract y d]
partTwo :: String -> Int partTwo :: String -> Int
partTwo input = undefined partTwo input = length antiNodes
pairs :: [a] -> [(a, a)]
pairs xs = mapMaybe parse $ subsequences xs
where where
parse :: [a] -> Maybe (a, a) matrix = M.buildMatrix (lines input)
parse [x, y] = Just (x, y) combinations = nodePairs matrix
parse _ = Nothing antiNodes = nub $ concatMap (uncurry getAntiNodes) combinations
getAntiNodes :: Position -> Position -> [AntiNode] getAntiNodes x y = case distance x y of
getAntiNodes (xrow, xcol) (yrow, ycol) = case distance of (0, 0) -> []
(0, 0) -> [] d -> computePointsAtDistance x d add ++ computePointsAtDistance y d substract
(drow, dcol) -> [(xrow + drow, xcol + dcol), (yrow - drow, ycol - dcol)]
where computePointsAtDistance point dist f =
distance = (xrow - yrow, xcol - ycol) let point' = f point dist
in if M.isInBounds point matrix
then point : computePointsAtDistance point' dist f
else []
nodePairs :: Matrix Char -> [(Node, Node)]
nodePairs 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)

27
test/Day8Spec.hs Normal file
View file

@ -0,0 +1,27 @@
module Day8Spec (spec) where
import Day8 (partOne, partTwo)
import Test.Hspec
spec :: Spec
spec = do
describe "PartOne" $ do
it "works" $ do
partOne input `shouldBe` 14
describe "PartTwo" $ do
it "works" $ do
partTwo input `shouldBe` 34
where
input =
"............\n\
\........0...\n\
\.....0......\n\
\.......0....\n\
\....0.......\n\
\......A.....\n\
\............\n\
\............\n\
\........A...\n\
\.........A..\n\
\............\n\
\............"