-
Notifications
You must be signed in to change notification settings - Fork 0
/
08.hs
63 lines (43 loc) · 1.73 KB
/
08.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
import Lib
data Direction = North | East | South | West
type Coord = (Int, Int)
type Size = (Int, Int)
type Grid = [[Int]]
type Input = (Size, Grid)
main :: IO ()
main = aoc 2022 8 setup solve1 solve2 ["1"]
solve1 :: Input -> Int
solve1 input@(size, _) = length $ filter (isVisible input) $ coords size
solve2 input@(size, _) = maximum $ map (scenicScore input) $ coords size
setup :: String -> Input
setup inp = ((length grid, length $ head grid), grid)
where
grid = map parseLine $ lines inp
parseLine :: String -> [Int]
parseLine = map (read . (: []))
isVisible :: Input -> Coord -> Bool
isVisible input p = any (canSeeEdge input p) [North, East, South, West]
scenicScore :: Input -> Coord -> Int
scenicScore input p = product $ map (visibleTrees input p) [North, East, South, West]
canSeeEdge :: Input -> Coord -> Direction -> Bool
canSeeEdge (size, grid) p d = all ((< at grid p) . at grid) $ steps d size p
visibleTrees :: Input -> Coord -> Direction -> Int
visibleTrees (size, grid) p d = length $ takeWhileInclusive ((< at grid p) . at grid) $ steps d size p
steps :: Direction -> Size -> Coord -> [Coord]
steps d size = takeWhile (inGrid size) . iterate (step d) . step d
step :: Direction -> Coord -> Coord
step North (i, j) = (i - 1, j)
step East (i, j) = (i, j + 1)
step South (i, j) = (i + 1, j)
step West (i, j) = (i, j - 1)
inGrid :: Size -> Coord -> Bool
inGrid (h, w) (i, j) = 0 <= i && i < h && 0 <= j && j < w
coords :: Size -> [Coord]
coords (h, w) = [(i, j) | i <- [0 .. h - 1], j <- [0 .. w - 1]]
at :: Grid -> Coord -> Int
at grid (i, j) = grid !! i !! j
takeWhileInclusive :: (a -> Bool) -> [a] -> [a]
takeWhileInclusive f [] = []
takeWhileInclusive f (x : xs)
| f x = x : takeWhileInclusive f xs
| otherwise = [x]