X-Git-Url: https://git.njae.me.uk/?p=advent-of-code-20.git;a=blobdiff_plain;f=advent13%2Fsrc%2Fadvent13.hs;fp=advent13%2Fsrc%2Fadvent13.hs;h=bb4117ef38c0ef779db4d4f2fa7f5b83a8d75f9f;hp=0000000000000000000000000000000000000000;hb=7f33f392172a57f78d4de4a94af76a2f08428b66;hpb=0f78ee34867c196e4ac5d35c96334f0b644c23d9 diff --git a/advent13/src/advent13.hs b/advent13/src/advent13.hs new file mode 100644 index 0000000..bb4117e --- /dev/null +++ b/advent13/src/advent13.hs @@ -0,0 +1,66 @@ +-- import Debug.Trace + +import Data.Text (Text) +-- import qualified Data.Text as T +import qualified Data.Text.IO as TIO + +import Data.Attoparsec.Text +-- import Data.Attoparsec.Combinator +import Control.Applicative +import Data.Maybe +import Data.List +import Math.NumberTheory.Moduli.Chinese + + + +main :: IO () +main = + do text <- TIO.readFile "data/advent13.txt" + let (timestamp, busses) = successfulParse text + print timestamp + print busses + print $ part1 timestamp busses + print $ part2 busses + +part1 timestamp maybeBusses = eBus * eTime + where busses = catMaybes maybeBusses + busDepartures = map (busAndTime timestamp) busses + (eBus, eTime) = head $ sortOn snd busDepartures + +part2 maybeBusses = b - a + where (a, b) = earliestGroup $ periodOffsets maybeBusses + + +busAndTime timestamp period = (period, earliestDeparture timestamp period) + +earliestDeparture timestamp period = period - (timestamp `mod` period) + +periodOffsets :: [Maybe Integer] -> [(Integer, Integer)] +periodOffsets maybeBusses = offsetBusses + where offsetMaybeBusses = zip [0..] maybeBusses + offsetJustBusses = filter (isJust . snd) offsetMaybeBusses + offsetBusses = map (\(o, b) -> (o, fromJust b)) offsetJustBusses + + +earliestGroup :: [(Integer, Integer)] -> (Integer, Integer) +earliestGroup offsetBusses = foldl1 chineseStep offsetBusses + + +chineseStep (n1, m1) (n2, m2) = (n, m1 * m2) + where n = fromJust $ chinese (n1, m1) (n2, m2) + + +-- Parse the input file + +timeBusP = (,) <$> decimal <* endOfLine <*> busPeriodsP + +busPeriodsP = busPeriodP `sepBy` (string ",") + +busPeriodP = (Just <$> decimal) <|> ("x" *> pure Nothing) + + +successfulParse :: Text -> (Integer, [Maybe Integer]) +successfulParse input = + case parseOnly timeBusP input of + Left _err -> (0, []) -- TIO.putStr $ T.pack $ parseErrorPretty err + Right timeBus -> timeBus