Skip to content

Commit 68f6a8e

Browse files
committed
day 8
1 parent a65720d commit 68f6a8e

File tree

4 files changed

+83
-23
lines changed

4 files changed

+83
-23
lines changed

aoc2024.cabal

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ source-repository head
2525

2626
library
2727
exposed-modules:
28+
Data.List.Extra
2829
Data.Matrix
2930
Day1
3031
Day2
@@ -62,6 +63,7 @@ test-suite aoc2024-test
6263
Day5Spec
6364
Day6Spec
6465
Day7Spec
66+
Day8Spec
6567
Paths_aoc2024
6668
autogen-modules:
6769
Paths_aoc2024

src/Data/List/Extra.hs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module Data.List.Extra (combinations, pairs) where
2+
3+
import Data.List (subsequences)
4+
import Data.Maybe (mapMaybe)
5+
6+
combinations :: Int -> [a] -> [[a]]
7+
combinations k xs = filter ((== k) . length) $ subsequences xs
8+
9+
pairs :: [a] -> [(a, a)]
10+
pairs xs = mapMaybe parse $ combinations 2 xs
11+
where
12+
parse :: [a] -> Maybe (a, a)
13+
parse [x, y] = Just (x, y)
14+
parse _ = Nothing

src/Day8.hs

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,51 @@
11
module Day8 (partOne, partTwo) where
22

3-
import Data.List (nub, subsequences)
3+
import Data.List (nub)
4+
import Data.List.Extra (pairs)
45
import qualified Data.Map.Lazy as Map
5-
import Data.Matrix (Position)
6+
import Data.Matrix (Matrix, Position)
67
import qualified Data.Matrix as M
7-
import Data.Maybe (mapMaybe)
88

9-
type AntiNode = (Int, Int)
9+
type Node = (Int, Int)
1010

1111
partOne :: String -> Int
12-
partOne input = length $ filter (`M.isInBounds` matrix) $ nub $ concatMap (uncurry getAntiNodes) combinations
12+
partOne input = length $ filter (`M.isInBounds` grid) $ nub antiNodes
1313
where
14-
matrix = M.buildMatrix (lines input)
15-
noDotsMatrix = M.filter (/= '.') matrix
16-
pointGroups = Map.elems $ M.groupByWith (\(position, value) -> (value, position)) noDotsMatrix
17-
combinations = concatMap pairs pointGroups
14+
grid = M.buildMatrix (lines input)
15+
antiNodes = concatMap (uncurry getAntiNodes) $ nodePairs grid
1816

19-
partTwo :: String -> Int
20-
partTwo input = undefined
17+
getAntiNodes x y = case distance x y of
18+
(0, 0) -> []
19+
d -> [add x d, substract y d]
2120

22-
pairs :: [a] -> [(a, a)]
23-
pairs xs = mapMaybe parse $ subsequences xs
24-
where
25-
parse :: [a] -> Maybe (a, a)
26-
parse [x, y] = Just (x, y)
27-
parse _ = Nothing
28-
29-
getAntiNodes :: Position -> Position -> [AntiNode]
30-
getAntiNodes (xrow, xcol) (yrow, ycol) = case distance of
31-
(0, 0) -> []
32-
(drow, dcol) -> [(xrow + drow, xcol + dcol), (yrow - drow, ycol - dcol)]
21+
partTwo :: String -> Int
22+
partTwo input = length antiNodes
3323
where
34-
distance = (xrow - yrow, xcol - ycol)
24+
matrix = M.buildMatrix (lines input)
25+
combinations = nodePairs matrix
26+
antiNodes = nub $ concatMap (uncurry getAntiNodes) combinations
27+
28+
getAntiNodes x y = case distance x y of
29+
(0, 0) -> []
30+
d -> computePointsAtDistance x d add ++ computePointsAtDistance y d substract
31+
32+
computePointsAtDistance point dist f =
33+
let point' = f point dist
34+
in if M.isInBounds point matrix
35+
then point : computePointsAtDistance point' dist f
36+
else []
37+
38+
nodePairs :: Matrix Char -> [(Node, Node)]
39+
nodePairs matrix =
40+
let noDotsMatrix = M.filter (/= '.') matrix
41+
pointGroups = Map.elems $ M.groupByWith (\(position, value) -> (value, position)) noDotsMatrix
42+
in concatMap pairs pointGroups
43+
44+
substract :: Position -> (Int, Int) -> (Int, Int)
45+
substract (x, y) (dx, dy) = (x - dx, y - dy)
46+
47+
add :: Position -> (Int, Int) -> (Int, Int)
48+
add (x, y) (dx, dy) = (x + dx, y + dy)
49+
50+
distance :: Position -> Position -> (Int, Int)
51+
distance (xrow, xcol) (yrow, ycol) = (xrow - yrow, xcol - ycol)

test/Day8Spec.hs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
module Day8Spec (spec) where
2+
3+
import Day8 (partOne, partTwo)
4+
import Test.Hspec
5+
6+
spec :: Spec
7+
spec = do
8+
describe "PartOne" $ do
9+
it "works" $ do
10+
partOne input `shouldBe` 14
11+
describe "PartTwo" $ do
12+
it "works" $ do
13+
partTwo input `shouldBe` 34
14+
where
15+
input =
16+
"............\n\
17+
\........0...\n\
18+
\.....0......\n\
19+
\.......0....\n\
20+
\....0.......\n\
21+
\......A.....\n\
22+
\............\n\
23+
\............\n\
24+
\........A...\n\
25+
\.........A..\n\
26+
\............\n\
27+
\............"

0 commit comments

Comments
 (0)