This commit is contained in:
Jens Kadenbach
2022-12-08 13:09:39 +01:00
parent 435a06fd59
commit b9df0aa858
7 changed files with 265 additions and 1 deletions

84
src/Day8.hs Normal file
View File

@@ -0,0 +1,84 @@
module Day8 (
Forest,
Visibillity,
parseForest,
checkVisibility,
countVisible,
findMaxScenicScore,
viewingDistance,
day8
)where
import qualified Data.Matrix as M
import Data.Matrix ((!))
import Data.Char (isDigit)
import qualified Data.Vector as V
import Data.Monoid (Sum (..), getSum, Product (..), getProduct)
import Control.Arrow ((>>>))
type Forest = M.Matrix Int
type Visibillity = M.Matrix Bool
parseForest :: String -> Forest
parseForest input = M.fromList rows cols asNumbers
where
ls = lines input
cols = length (head ls)
rows = length ls
asNumbers :: [Int]
asNumbers = map (read . (: [])) . filter isDigit $ input
checkAgainstNeighbours :: (Int -> [V.Vector Int] -> a) -> Forest -> M.Matrix a
checkAgainstNeighbours f forest = M.matrix (M.nrows forest) (M.ncols forest) check
where
check(x, y) =
let row = M.getRow x forest
col = M.getCol y forest
-- left and top are reversed to order the as seen from (x,y)
left = V.reverse $ V.take (y - 1) row
right = V.drop y row
top = V.reverse $ V.take (x - 1) col
bottom = V.drop x col
v = forest ! (x,y)
in f v [left, right, top, bottom]
checkVisibility :: Forest -> Visibillity
checkVisibility = checkAgainstNeighbours isVisible
where
isVisible v = any (all (< v))
countVisible :: Visibillity -> Int
countVisible vis = getSum $ foldMap (Sum . isTrue) vis
where
isTrue True = 1
isTrue False = 0
checkScenicScores :: Forest -> M.Matrix Int
checkScenicScores = checkAgainstNeighbours allDistances
where
allDistances tree neighbors = getProduct $ foldMap (Product . viewingDistance tree) neighbors
viewingDistance :: Int -> V.Vector Int -> Int
viewingDistance treeHeight neighbors
| V.length neighbors == 0 = 0
| V.head neighbors >= treeHeight = 1
| V.head neighbors < treeHeight = 1 + viewingDistance treeHeight (V.tail neighbors)
| otherwise = 0
findMaxScenicScore :: Forest -> Int
findMaxScenicScore forest = maximum $ M.toList scores
where
scores = checkScenicScores forest
day8 :: IO ()
day8 = do
input <- readFile "ressources/day08-input"
putStrLn "Day8"
let forest = parseForest input
let visibleTrees = checkVisibility >>>
countVisible $ forest
putStrLn ("Number of visible trees is " ++ show visibleTrees)
let highestScenicScore = findMaxScenicScore forest
putStrLn ("Highest scenic score is " ++ show highestScenicScore)

View File

@@ -9,6 +9,7 @@ import Day4
import Day5
import Day6
import Day7
import Day8
someFunc :: IO ()
someFunc = do
@@ -25,5 +26,7 @@ someFunc = do
day6
putStrLn "-----------"
day7
putStrLn "-----------"
day8