Done part 2
[advent-of-code-20.git] / advent13 / src / advent13.hs
1 -- import Debug.Trace
2
3 import Data.Text (Text)
4 -- import qualified Data.Text as T
5 import qualified Data.Text.IO as TIO
6
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
13
14
15
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
24
25 part1 timestamp maybeBusses = eBus * eTime
26 where busses = catMaybes maybeBusses
27 busDepartures = map (busAndTime timestamp) busses
28 (eBus, eTime) = head $ sortOn snd busDepartures
29
30 part2 maybeBusses = b - a
31 where (a, b) = earliestGroup $ periodOffsets maybeBusses
32
33
34 busAndTime timestamp period = (period, earliestDeparture timestamp period)
35
36 earliestDeparture timestamp period = period - (timestamp `mod` period)
37
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
43
44
45 earliestGroup :: [(Integer, Integer)] -> (Integer, Integer)
46 earliestGroup offsetBusses = foldl1 chineseStep offsetBusses
47
48
49 chineseStep (n1, m1) (n2, m2) = (n, m1 * m2)
50 where n = fromJust $ chinese (n1, m1) (n2, m2)
51
52
53 -- Parse the input file
54
55 timeBusP = (,) <$> decimal <* endOfLine <*> busPeriodsP
56
57 busPeriodsP = busPeriodP `sepBy` (string ",")
58
59 busPeriodP = (Just <$> decimal) <|> ("x" *> pure Nothing)
60
61
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