git.haldean.org aoc-2018 / c065c4c
ugly but working day 4! Haldean Brown 2 years ago
1 changed file(s) with 44 addition(s) and 4 deletion(s). Raw diff Collapse all Expand all
0 import Data.Fixed
01 import Data.Function
12 import Data.Maybe
23 import Data.Time
113114 shiftGuard :: Shift -> Int
114115 shiftGuard (Shift gid _) = gid
115116
116 guardSleepTimes :: [Shift] -> [(Integer, Int)]
117 allGuards :: [Shift] -> S.Set Int
118 allGuards = S.fromList . map shiftGuard
119
120 guardSleepTimes :: [Shift] -> [(Integer, Int)] -- sleep time, guard id
117121 guardSleepTimes shifts =
118 let guards = S.fromList $ map shiftGuard shifts
119 in L.sort $ map (\gid -> (sum $ map getSleepTime $ filter (\s -> shiftGuard s == gid) shifts, gid)) $ S.toList guards
122 L.sort
123 $ map (\gid -> (sum $ map getSleepTime $ filter (\s -> shiftGuard s == gid) shifts, gid))
124 $ S.toList
125 $ allGuards shifts
126
127 sleepiestGuard :: [Shift] -> Int
128 sleepiestGuard = snd . L.maximum . guardSleepTimes
129
130 minute :: UTCTime -> Int
131 minute = (\s -> floor $ (s `mod'` 3600) / 60) . utctDayTime
132
133 isAsleepAt :: Int -> Shift -> Bool
134 isAsleepAt m (Shift _ pairs) = any id $ map minuteIsBetween pairs where
135 minuteIsBetween (t1, t2) = (minute t1 <= m) && (m < minute t2)
136
137 guardMinutes :: Int -> [Shift] -> [(Int, Int)]
138 guardMinutes g allShifts =
139 let shifts = filter ((==) g . shiftGuard) allShifts
140 minutes = [0..59]
141 in map (countSleepMinutes shifts) minutes where
142 countSleepMinutes shifts m = (length $ filter (isAsleepAt m) shifts, m)
143
144 sleepiestMinute :: Int -> [Shift] -> (Int, Int) -- sleeps, minute
145 sleepiestMinute g allShifts = L.maximum $ guardMinutes g allShifts
146
147 sleepiestGuardMinute :: [Shift] -> (Int, Int, Int) -- sleeps, minute, guard
148 sleepiestGuardMinute allShifts =
149 let guards = S.toList $ allGuards allShifts
150 in L.maximum $ map (\g -> let (s, m) = sleepiestMinute g allShifts in (s, m, g)) guards
120151
121152 main :: IO ()
122153 main = do
123154 records <- fmap (parse (sepEndBy parseLine endOfLine) "input.txt") (readFile "input.txt")
124155 case records of
125156 Right rs -> do
126 mapM_ print $ guardSleepTimes $ getShifts rs
157 let shifts = getShifts rs
158 let guard = sleepiestGuard shifts
159 let guardMin = snd $ sleepiestMinute guard shifts
160 putStrLn $ "1: sleepiest guard: " ++ show guard
161 putStrLn $ "1: sleepiest minute: " ++ show guardMin
162 putStrLn $ "1: result: " ++ show (guard * guardMin)
163 let (s2, m2, g2) = sleepiestGuardMinute shifts
164 putStrLn $ "2: sleepiest guard: " ++ show g2
165 putStrLn $ "2: sleepiest minute: " ++ show m2
166 putStrLn $ "2: result: " ++ show (g2 * m2)
127167 Left err -> print err