Day 8
This commit is contained in:
84
src/Day8.hs
Normal file
84
src/Day8.hs
Normal 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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user