-
Notifications
You must be signed in to change notification settings - Fork 0
/
run.hs
90 lines (72 loc) · 2.26 KB
/
run.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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
{-# Language OverloadedStrings #-}
import Data.Ord
import Data.List
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
import Text.Megaparsec
import Text.Megaparsec.Char
type Parser = Parsec (ErrorItem Char) String
unsafeRight :: Show a => Either a b -> b
unsafeRight (Right x) = x
unsafeRight (Left x) = error $ show x
type Time = Int
type GuardId = Int
data Event = ShiftStart GuardId
| FallsAsleep Time
| WakesUp Time
deriving (Show, Eq)
int :: Parser Int
int = read <$> many digitChar
timep = do
"[1518-" *> some digitChar *> "-" *> some digitChar *> " "
hour <- int
":"
minute <- int
"]"
pure minute
eventp = do
time <- timep
ShiftStart <$> (" Guard #" *> int <* " begins shift")
<|> FallsAsleep time <$ " falls asleep"
<|> WakesUp time <$ " wakes up"
type Counter a = Map a Int
counter :: Ord a => [a] -> Counter a
counter = Map.fromListWith (+) . flip zip (repeat 1)
parseAll =
map unsafeRight .
map (parse eventp "") . filter (not . null) . sort . lines
guardAsleepTimes events =
let updateGuardTimes m gid ft wt =
Map.unionWith (Map.unionWith (+))
m
(Map.singleton gid (counter [ft..wt-1]))
go (m, _, _) (ShiftStart gid) = (m, Just gid, Nothing)
go (m, Just gid, Nothing) (FallsAsleep t) = (m, Just gid, Just t)
go (m, Just gid, Just ft) (WakesUp wt) =
(updateGuardTimes m gid ft wt, Just gid, Nothing)
go _ _ = undefined
(times, _, _) = foldl go (Map.empty, Nothing, Nothing) events
in
times
values :: Map a b -> [b]
values = map snd . Map.toList
part1 input = id * t
where (id, asleep) = maximumBy (comparing (sum . values . snd))
. Map.toList
. guardAsleepTimes $ input
(t, _) = maximumBy (comparing snd) (Map.toList asleep)
thd :: (a, b, c) -> c
thd (_, _, z) = z
flatten :: Map a (Map b c) -> [(a, b, c)]
flatten m = do
(x, vals) <- Map.toList m
(y, z) <- Map.toList vals
pure (x, y, z)
part2 input = id * t
where (id, t, _) = maximumBy (comparing thd)
. flatten
. guardAsleepTimes $ input
main = do
input <- parseAll <$> readFile "input.txt"
print (part1 input)
print (part2 input)