1 -- import Debug.Trace
3 import Data.Text (Text)
4 -- import qualified Data.Text as T
5 import qualified Data.Text.IO as TIO
7 import Data.Attoparsec.Text
8 -- import Data.Attoparsec.Combinator
9 import Control.Applicative
10 import Data.Maybe
11 import Data.List
12 import Math.NumberTheory.Moduli.Chinese
16 main :: IO ()
17 main =
18 do text <- TIO.readFile "data/advent13.txt"
19 let (timestamp, busses) = successfulParse text
20 -- print timestamp
21 -- print busses
22 print \$ part1 timestamp busses
23 print \$ part2 busses
25 part1 timestamp maybeBusses = eBus * eTime
26 where busses = catMaybes maybeBusses
27 busDepartures = map (busAndTime timestamp) busses
28 (eBus, eTime) = head \$ sortOn snd busDepartures
30 part2 maybeBusses = b - a
31 where (a, b) = earliestGroup \$ periodOffsets maybeBusses
34 busAndTime timestamp period = (period, earliestDeparture timestamp period)
36 earliestDeparture timestamp period = period - (timestamp `mod` period)
38 periodOffsets :: [Maybe Integer] -> [(Integer, Integer)]
39 periodOffsets maybeBusses = offsetBusses
40 where offsetMaybeBusses = zip [0..] maybeBusses
41 offsetJustBusses = filter (isJust . snd) offsetMaybeBusses
42 offsetBusses = map (\(o, b) -> (o, fromJust b)) offsetJustBusses
45 earliestGroup :: [(Integer, Integer)] -> (Integer, Integer)
46 earliestGroup offsetBusses = foldl1 chineseStep offsetBusses
49 chineseStep (n1, m1) (n2, m2) = (n, m1 * m2)
50 where n = fromJust \$ chinese (n1, m1) (n2, m2)
53 -- Parse the input file
55 timeBusP = (,) <\$> decimal <* endOfLine <*> busPeriodsP
57 busPeriodsP = busPeriodP `sepBy` (string ",")
59 busPeriodP = (Just <\$> decimal) <|> ("x" *> pure Nothing)
62 successfulParse :: Text -> (Integer, [Maybe Integer])
63 successfulParse input =
64 case parseOnly timeBusP input of
65 Left _err -> (0, []) -- TIO.putStr \$ T.pack \$ parseErrorPretty err
66 Right timeBus -> timeBus