63 lines
1.7 KiB
Haskell
63 lines
1.7 KiB
Haskell
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]
|