adventofcode/2022/app/Day8/Main.hs

60 lines
1.7 KiB
Haskell

module Day8.Main where
import System.IO
import Data.List
main :: IO ()
main = do
putStrLn "Day 8"
handle <- openFile "app/Day8/input" ReadMode
contents <- hGetContents handle
let r1 = part1 contents
putStrLn $ "part 1: " ++ show r1
let r2 = part2 contents
putStrLn $ "part 2: " ++ show r2
type Tree = (Int,[Int],[Int],[Int],[Int]) -- Self, N, E, S, W
enumerate :: [a] -> [(Int, a)]
enumerate = zip [0..]
parseData :: String -> [[Int]]
parseData contents = (map . map) (read . singleton :: Char -> Int) $ lines contents
toTrees :: [[Int]] -> [Tree]
toTrees rows = [(tree, north r c, east r c, south r c, west r c) | (r, line) <- enumerate rows, (c, tree) <- enumerate line]
where
columns = transpose rows
east r c = drop (c + 1) $ rows !! r
west r c = reverse $ take c $ rows !! r
north r c = reverse $ take r $ columns !! c
south r c = drop (r + 1) $ columns !! c
isVisible :: Int -> [Int] -> Bool
isVisible _ [] = True
isVisible t ts = all (< t) ts
invisibleFromOutside :: Tree -> Bool
invisibleFromOutside (t,n,e,s,w) = all (not . isVisible t) [n,e,s,w]
part1 :: String -> Int
part1 = length . filter (not . invisibleFromOutside) . toTrees . parseData
-- Includive version of takeWhile (because lentgh takeWhile + 1 doesn't work for when the outer border is the reason you can't see further)
takeWhileI :: (a -> Bool) -> [a] -> [a]
takeWhileI _ [] = []
takeWhileI p (x:xs) =
x : if p x then takeWhileI p xs else []
viewingDistance :: Int -> [Int] -> Int
viewingDistance t ts = length $ takeWhileI (< t) ts
scenicScore :: Tree -> Int
scenicScore (t,n,e,s,w) = product $ map (viewingDistance t) [n,e,s,w]
part2 :: String -> Int
part2 = maximum . map scenicScore . toTrees . parseData