aboutsummaryrefslogtreecommitdiff
path: root/2020/03-Toboggan_Trajectory/second.hs
diff options
context:
space:
mode:
authorJulien Dessaux2023-03-10 00:25:47 +0100
committerJulien Dessaux2023-03-10 00:25:47 +0100
commit089b9ee57a6e0e3f867c4f23c075c2653508de6b (patch)
treede67a04c480bd67cd4fac4a805dde95f011ebe4e /2020/03-Toboggan_Trajectory/second.hs
parentImprove parsers of 2020-02 (diff)
downloadadvent-of-code-089b9ee57a6e0e3f867c4f23c075c2653508de6b.tar.gz
advent-of-code-089b9ee57a6e0e3f867c4f23c075c2653508de6b.tar.bz2
advent-of-code-089b9ee57a6e0e3f867c4f23c075c2653508de6b.zip
2020-03 in haskell
Diffstat (limited to '')
-rw-r--r--2020/03-Toboggan_Trajectory/second.hs60
1 files changed, 60 insertions, 0 deletions
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