From 089b9ee57a6e0e3f867c4f23c075c2653508de6b Mon Sep 17 00:00:00 2001 From: Julien Dessaux Date: Fri, 10 Mar 2023 00:25:47 +0100 Subject: 2020-03 in haskell --- 2020/03-Toboggan_Trajectory/second.hs | 60 +++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 2020/03-Toboggan_Trajectory/second.hs (limited to '2020/03-Toboggan_Trajectory/second.hs') diff --git a/2020/03-Toboggan_Trajectory/second.hs b/2020/03-Toboggan_Trajectory/second.hs new file mode 100644 index 0000000..54144c1 --- /dev/null +++ b/2020/03-Toboggan_Trajectory/second.hs @@ -0,0 +1,60 @@ +-- requires cabal install --lib megaparsec +module Main (main) where + +import Control.Monad (void, when) +import Data.List (foldl') +import Data.Void +import Text.Megaparsec +import Text.Megaparsec.Char +import System.Exit (die) + +exampleExpectedOutput = 336 + +type Line = [Bool] +type Field = [Line] + +type Parser = Parsec Void String + +parseElt :: Parser Bool +parseElt = do + c <- (char '#') <|> (char '.') + return $ c == '#' + +parseLine :: Parser Line +parseLine = some parseElt <* char '\n' + +parseField :: Parser Field +parseField = some parseLine <* eof + +parseInput :: String -> IO Field +parseInput filename = do + input <- readFile filename + case runParser parseField filename input of + Left bundle -> die $ errorBundlePretty bundle + Right field -> return field + +computeOne :: Field -> Int-> Int +computeOne field step = snd $ foldl' tree (0, 0) field + where + tree :: (Int, Int) -> Line -> (Int, Int) + tree (index, trees) l = (next index, trees + if l !! index then 1 else 0) + next n = (n + step) `mod` fieldLen + fieldLen = length $ field !! 0 + +steps = [1, 3, 5, 7] + +compute :: Field -> Int +compute field = foldr (*) 1 (computeOne (skipEveryOtherLine field) 1 : map (computeOne field) steps) + where + skipEveryOtherLine :: Field -> Field + skipEveryOtherLine [] = [] + skipEveryOtherLine (x:[]) = [] + skipEveryOtherLine (x:y:xs) = x : skipEveryOtherLine xs + +main :: IO () +main = do + example <- parseInput "example" + let exampleOutput = compute example + when (exampleOutput /= exampleExpectedOutput) (die $ "example failed: got " ++ show exampleOutput ++ " instead of " ++ show exampleExpectedOutput) + input <- parseInput "input" + print $ compute input -- cgit v1.2.3