1 {-# LANGUAGE NegativeLiterals #-}
2 {-# LANGUAGE FlexibleContexts #-}
3 {-# LANGUAGE OverloadedStrings #-}
5 import Data.Text (Text)
6 import qualified Data.Text as T
7 import qualified Data.Text.IO as TIO
10 import qualified Text.Megaparsec.Lexer as L
11 import Text.Megaparsec.Text (Parser)
13 import qualified Control.Applicative as CA
15 type ScannerDef = (Integer, Integer)
16 type Scanner = Integer -> Integer
21 text <- TIO.readFile "data/advent13.txt"
22 let scannerDefs = successfulParse text
23 print $ part1 scannerDefs
24 print $ part2 scannerDefs
27 part1 :: [ScannerDef] -> Integer
28 part1 = sum . map (uncurry (*)) . filter (\(d, r) -> scanner d r 0 == 0)
31 part2 :: [ScannerDef] -> Integer
32 part2 scannerDefs = head $ filter (canPass scanners) [0..]
33 where scanners = scanify scannerDefs
36 scanify :: [ScannerDef] -> [Scanner]
37 scanify = map (uncurry scanner)
39 canPass :: [Scanner] -> Integer -> Bool
40 canPass scannersF t = all (\s -> s t /= 0) scannersF
43 scanner :: Integer -> Integer -> Integer -> Integer
44 scanner depth range t =
45 let t' = (t + depth) `mod` ((range - 1) * 2)
48 else range - t' - 1 -- t' + (t' - range + 1) * -2
52 sc = L.space (skipSome spaceChar) CA.empty CA.empty
55 integer = lexeme L.integer
58 scannersP = many scannerP
60 scannerP = (,) <$> integer <*> (symb ":" *> integer)
62 successfulParse :: Text -> [ScannerDef]
63 successfulParse input =
64 case parse scannersP "input" input of
65 Left err -> [] -- TIO.putStr $ T.pack $ parseErrorPretty err
66 Right scanners -> scanners