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