60 lines
1.7 KiB
Haskell
60 lines
1.7 KiB
Haskell
module Day8.Main (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
|