-
Notifications
You must be signed in to change notification settings - Fork 0
/
Day11.hs
107 lines (84 loc) · 2.71 KB
/
Day11.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE TupleSections #-}
module Day11 where
import Data.Array (Array)
import Data.Bifunctor
import Data.Foldable
import Data.Maybe
import Text.ParserCombinators.ReadP
import Harness
import ParseHelper
import Data.Array qualified as A
import Data.List qualified as L
main :: IO ()
main = getInputAndSolve (parseInputRaw parseGrid) (sumPairPaths 1) (sumPairPaths 999_999)
-- SOLVE
sumPairPaths :: Int -> Grid -> Int
sumPairPaths expansionAmount g =
let galaxyLocs = expandUniverse expansionAmount g
pairs =
concatMap (\(g1, gs) -> (g1,) <$> gs)
. zip galaxyLocs
$ L.tails (drop 1 galaxyLocs)
in sum $ map calcDistance pairs
where
calcDistance :: ((Int, Int), (Int, Int)) -> Int
calcDistance ((x1, y1), (x2, y2)) = abs (x2 - x1) + abs (y2 - y1)
-- HELPERS
expandUniverse :: Int -> Grid -> [(Int, Int)]
expandUniverse expansionAmount g =
let initialGalaxies = findGalaxies g
(blankCols, blankRows) =
bimap incrementSuccessive incrementSuccessive $
findBlanks g
in foldl' expandRows (foldl' expandColumns initialGalaxies blankCols) blankRows
where
incrementSuccessive :: [Int] -> [Int]
incrementSuccessive = zipWith (\i -> (+) (i * expansionAmount)) [0 ..]
expandColumns :: [(Int, Int)] -> Int -> [(Int, Int)]
expandColumns gs blankCol =
map
( \coords@(x, y) ->
if x > blankCol
then (expansionAmount + x, y)
else coords
)
gs
expandRows :: [(Int, Int)] -> Int -> [(Int, Int)]
expandRows gs blankRow =
map
( \coords@(x, y) ->
if y > blankRow
then (x, expansionAmount + y)
else coords
)
gs
findGalaxies :: Grid -> [(Int, Int)]
findGalaxies g =
mapMaybe (fmap fst . sequence) $ A.assocs g.fromGrid
findBlanks :: Grid -> ([Int], [Int])
findBlanks Grid {fromGrid} =
let (_, (cols, rows)) = A.bounds fromGrid
in ( [ col
| col <- [0 .. cols]
, let colVals = [fromGrid A.! (col, row) | row <- [0 .. rows]]
, null $ catMaybes colVals
]
, [ row
| row <- [0 .. rows]
, let rowVals = [fromGrid A.! (col, row) | col <- [0 .. cols]]
, null $ catMaybes rowVals
]
)
-- PARSE
newtype Grid = Grid
{ fromGrid :: Array (Int, Int) (Maybe ())
}
deriving (Show)
parseGrid :: ReadP Grid
parseGrid =
Grid
<$> parseValueGrid (choice [Just () <$ char '#', Nothing <$ char '.'])
<* newline