-
Notifications
You must be signed in to change notification settings - Fork 0
/
day13.hs
69 lines (55 loc) · 1.96 KB
/
day13.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import Data.List
import Data.Functor
import Control.Applicative
import Data.Either
import Text.Megaparsec
import Text.Megaparsec.Char
import qualified Text.Megaparsec.Char.Lexer as L
import Data.Void
import Control.Monad
import Control.Monad.Combinators
-- ===========================================================================
-- Data
-- ===========================================================================
type Parser = Parsec Void String
data Entry = ID Integer | X deriving (Show, Eq, Ord)
parseval = (ID <$> L.decimal) <|> (char 'x' $> X)
pEntries :: Parser [Entry]
pEntries = parseval `sepBy` char ','
getEntries = runParser pEntries ""
-- ===========================================================================
-- pt. 1 helpers
-- ===========================================================================
getArrivals (ID n) = [0, n..]
getArrivals X = []
isID (ID _) = True
isID _ = False
firstAvailable t l =
let
id = l!!1
a = head $ dropWhile (<t) l
in (a, id)
-- ===========================================================================
-- pt. 2
-- ===========================================================================
fromID (ID n, t) = (n, t)
fromID _ = error "don't fromID an X"
hasTime :: Integer -> (Entry, Integer) -> Bool
hasTime t (ID i, offset) = ((offset + t) `mod` i) == 0
solve t stepBy l@(i:is) =
if hasTime t i
then solve t (stepBy * (fst $ fromID i)) is
else solve (t+stepBy) stepBy l
solve t _ [] = t
-- ===========================================================================
main = do
f <- readFile "inputs/day13.txt"
let ls = lines f
let time = (read $ ls!!0) :: Integer
let entries = fromRight undefined (getEntries $ ls!!1)
let ids = filter (isID) entries
let arrivals = getArrivals <$> ids
let (a, id) = head $ sort $ firstAvailable time <$> arrivals
print $ id * (a - time)
let idAndOffset = sortOn fst $ filter (isID . fst) (zip entries [0..])
print $ solve 1 1 idAndOffset