-
Notifications
You must be signed in to change notification settings - Fork 0
/
Day10.hs
54 lines (46 loc) · 1.37 KB
/
Day10.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
module Day10
( part1
, part2
) where
import Control.Lens.Getter ((^.))
import Data.List (unfoldr)
import Data.List.Split (chunksOf)
import Helpers.Graph (Pos)
import Helpers.Parsers (integers)
import Linear.V2 (V2 (..), _x, _y)
findMessage :: [(Pos, Pos)] -> Maybe ([Pos], [(Pos, Pos)])
findMessage curState
| area newPos > area (map fst curState) = Nothing
| otherwise = Just (newPos, newState)
where
newState = map (\(a, b) -> (a + b, b)) curState
newPos = map fst newState
area :: [Pos] -> Int
area pos = (mX - mx) * (mY - my)
where
((mx, mX), (my, mY)) = bounds pos
bounds :: [Pos] -> ((Int, Int), (Int, Int))
bounds pos = ((mx, mX), (my, mY))
where
mx = minimum . map (^. _x) $ pos
mX = maximum . map (^. _x) $ pos
my = minimum . map (^. _y) $ pos
mY = maximum . map (^. _y) $ pos
render :: [Pos] -> String
render pos =
unlines . chunksOf (mX - mx + 1) $
[ if V2 x y `elem` pos
then '#'
else ' '
| y <- [my .. mY]
, x <- [mx .. mX]
]
where
((mx, mX), (my, mY)) = bounds pos
message :: String -> [[Pos]]
message =
unfoldr findMessage . map (\[a, b, c, d] -> (V2 a b, V2 c d)) . integers
part1 :: Bool -> String -> String
part1 _ = render . last . message
part2 :: Bool -> String -> String
part2 _ = show . length . message