53 lines
1.5 KiB
Haskell
53 lines
1.5 KiB
Haskell
|
|
import Data.Set as S
|
|
import Data.List (transpose)
|
|
import Data.Char (digitToInt)
|
|
import Debug.Trace (traceShowId)
|
|
|
|
type TreeSet = S.Set (Int, Int)
|
|
|
|
toIndices :: [a] -> [Int]
|
|
toIndices = fmap fst . zip [0..]
|
|
|
|
enumerate = zip [0..]
|
|
|
|
check :: Ord t1 => [t1] -> Int -> t1 -> [Int]
|
|
check [] i max = []
|
|
check (t:ts) i req = (if t > req then (i:) else id) $ check ts (i+1) (max t req)
|
|
|
|
addRow :: (Int -> (Int, Int)) -> [Int] -> TreeSet
|
|
addRow f ts = S.fromList (Prelude.map f (left ++ right)) where
|
|
check' ts = check ts 0 (-1)
|
|
left = check' ts
|
|
right = (\x -> length ts - x - 1) <$> check' (reverse ts)
|
|
|
|
evalOutside :: [[Int]] -> TreeSet
|
|
evalOutside xs = Prelude.foldr S.union S.empty (hor ++ ver) where
|
|
hor = (\(i, ts) -> addRow (i,) ts) <$> enumerate xs
|
|
ver = (\(i, ts) -> addRow (,i) ts) <$> enumerate (transpose xs)
|
|
|
|
|
|
|
|
scenicScore :: (Int, Int) -> [[Int]] -> Int
|
|
scenicScore (x,y) ts = product $ count <$> [reverse left, right, reverse up, down] where
|
|
(left, _:right) = Prelude.splitAt x (ts !! y)
|
|
(up, _:down) = Prelude.splitAt y (transpose ts !! x)
|
|
height = ts !! y !! x
|
|
count t = length t `min` (1 + length (takeWhile (<height) t))
|
|
|
|
allScenics :: [[Int]] -> [Int]
|
|
allScenics ts = Prelude.map (\c -> scenicScore c ts) coords where
|
|
coords = [(i,j) | i <- [0..length ts-1], j <- [0..length (head ts)-1]]
|
|
|
|
|
|
|
|
main :: IO ()
|
|
main = do
|
|
x <- lines <$> readFile "inputs/day08"
|
|
let ts = fmap (fmap digitToInt) x
|
|
|
|
putStr "part 1: "
|
|
print $ S.size $ evalOutside ts
|
|
|
|
putStr "part 2: "
|
|
print $ maximum (allScenics ts) |