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
12 import Math.NumberTheory.Moduli.Chinese
18 do text <- TIO.readFile "data/advent13.txt"
19 let (timestamp, busses) = successfulParse text
22 print $ part1 timestamp 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