ugly but working day 4!
Haldean Brown
3 years ago
0 | import Data.Fixed | |
0 | 1 | import Data.Function |
1 | 2 | import Data.Maybe |
2 | 3 | import Data.Time |
113 | 114 | shiftGuard :: Shift -> Int |
114 | 115 | shiftGuard (Shift gid _) = gid |
115 | 116 | |
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 | |
117 | 121 | 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 | |
120 | 151 | |
121 | 152 | main :: IO () |
122 | 153 | main = do |
123 | 154 | records <- fmap (parse (sepEndBy parseLine endOfLine) "input.txt") (readFile "input.txt") |
124 | 155 | case records of |
125 | 156 | 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) | |
127 | 167 | Left err -> print err |