62 lines
2.5 KiB
Haskell
62 lines
2.5 KiB
Haskell
import Data.Char
|
|
|
|
type TreeHeight=Int
|
|
data Tree = Tree TreeHeight [TreeHeight] [TreeHeight] [TreeHeight] [TreeHeight] deriving(Show)
|
|
|
|
parseTrees :: [[TreeHeight]] -> [TreeHeight] -> [[TreeHeight]] -> [Tree]
|
|
parseTrees linesAbove heights linesBelow = do
|
|
let heightsWithIndex = zipWith (,) heights [0..]
|
|
let trees=map (\heightWithIndex -> do
|
|
let (_,columnAbove) = getAlingedHeightsInColumn (linesAbove) heightWithIndex
|
|
let (_,columnBelow) = getAlingedHeightsInColumn linesBelow heightWithIndex
|
|
let (rowBefore,self:rowAfter) = splitAt (snd heightWithIndex) heights
|
|
Tree (fst heightWithIndex) columnAbove columnBelow (reverse rowBefore) rowAfter ) heightsWithIndex
|
|
let recrusiveResult = if (0 == length linesBelow) then [] else
|
|
(parseTrees (heights:linesAbove) (head linesBelow ) $ tail linesBelow)
|
|
trees <> recrusiveResult
|
|
|
|
isVisible :: Tree -> Bool
|
|
isVisible (Tree height columnAbove columnBelow rowBefore rowAfter) =
|
|
canBeSeen columnAbove ||
|
|
canBeSeen columnBelow ||
|
|
canBeSeen rowBefore ||
|
|
canBeSeen rowAfter
|
|
where canBeSeen = all (< height)
|
|
|
|
|
|
getTreeViewingScore :: Tree -> Int
|
|
getTreeViewingScore (Tree height columnAbove columnBelow rowBefore rowAfter) =
|
|
foldl (*) 1 $ map (scoreInOneDirection height) [columnBelow,columnAbove,rowAfter,rowBefore]
|
|
|
|
scoreInOneDirection :: TreeHeight -> [TreeHeight] -> Int
|
|
scoreInOneDirection height heights =let (a,b,c) = (foldl foldFunc (-1,0,True) heights) in b
|
|
where foldFunc :: (TreeHeight,Int,Bool) -> TreeHeight -> (TreeHeight,Int,Bool)
|
|
foldFunc (currentHeight,count,canSee) nextHeight
|
|
| not canSee = (currentHeight,count,canSee)
|
|
| nextHeight >= height = (currentHeight,count+1,False)
|
|
| nextHeight >= currentHeight = (max nextHeight currentHeight,count+1,True)
|
|
| nextHeight < currentHeight = (currentHeight,count+1,True)
|
|
|
|
|
|
|
|
getAlingedHeightsInColumn :: [[TreeHeight]] -> (TreeHeight,Int) -> (TreeHeight,[TreeHeight])
|
|
getAlingedHeightsInColumn rows ((ownHeight,index)) = (ownHeight, map (!! index) rows)
|
|
|
|
mainP1:: IO ()
|
|
mainP1 = do
|
|
content <- readFile "eight-input.txt"
|
|
let (firstRow:rest) = (map digitToInt) <$> lines content
|
|
let trees = parseTrees [] firstRow rest
|
|
print $ length $ filter isVisible trees
|
|
|
|
mainP2:: IO ()
|
|
mainP2 = do
|
|
content <- readFile "eight-input.txt"
|
|
let (firstRow:rest) = (map digitToInt) <$> lines content
|
|
let trees = parseTrees [] firstRow rest
|
|
mapM (print) trees
|
|
print $ maximum $ map getTreeViewingScore trees
|
|
|
|
|
|
main=mainP2
|