Solution for 4
This commit is contained in:
parent
3b10150e08
commit
3a9e7f70aa
85
4/4.hs
Normal file
85
4/4.hs
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
{-# LANGUAGE Strict #-}
|
||||||
|
module Main where
|
||||||
|
|
||||||
|
import Control.Applicative (some)
|
||||||
|
import Data.Function (on)
|
||||||
|
import Data.List (sort, foldl', maximumBy, groupBy, sortOn)
|
||||||
|
import Data.List.Split (split, dropInitBlank, keepDelimsL, whenElt, chunksOf)
|
||||||
|
import qualified Data.Map as M
|
||||||
|
import Data.Time (LocalTime, diffUTCTime, localTimeToUTC, utc, todMin, localTimeOfDay)
|
||||||
|
import Data.Time.Clock (NominalDiffTime)
|
||||||
|
import Data.Time.Format (parseTimeOrError, defaultTimeLocale)
|
||||||
|
import Text.Parsec
|
||||||
|
|
||||||
|
type GuardId = Int
|
||||||
|
data Action = BeginShift GuardId
|
||||||
|
| FallAsleep
|
||||||
|
| WakeUp
|
||||||
|
deriving (Show, Eq)
|
||||||
|
data Record = Record { recTime :: LocalTime, recAction :: Action }
|
||||||
|
deriving (Show, Eq)
|
||||||
|
type Round = [Record]
|
||||||
|
|
||||||
|
shiftBeginning :: Record -> Bool
|
||||||
|
shiftBeginning (Record _ (BeginShift _)) = True
|
||||||
|
shiftBeginning _ = False
|
||||||
|
|
||||||
|
instance Ord Record where
|
||||||
|
compare = compare `on` recTime
|
||||||
|
|
||||||
|
parseTime :: String -> LocalTime
|
||||||
|
parseTime = parseTimeOrError False defaultTimeLocale "%F %R"
|
||||||
|
|
||||||
|
diffLocalTime :: LocalTime -> LocalTime -> NominalDiffTime
|
||||||
|
diffLocalTime a b = diffUTCTime (localTimeToUTC utc a) (localTimeToUTC utc b)
|
||||||
|
|
||||||
|
inputP :: Parsec String () Record
|
||||||
|
inputP = Record <$> (tsP <* space) <*> (bsP <|> wP <|> aP)
|
||||||
|
where
|
||||||
|
intP = read <$> some digit
|
||||||
|
tsP = parseTime <$> (char '[' *> some (noneOf "]") <* char ']')
|
||||||
|
|
||||||
|
bsP = BeginShift
|
||||||
|
<$> (string "Guard" *> space *> char '#' *> intP <* space <* string "begins shift")
|
||||||
|
|
||||||
|
wP = WakeUp <$ string "wakes up"
|
||||||
|
aP = FallAsleep <$ string "falls asleep"
|
||||||
|
|
||||||
|
readInput :: [String] -> [Record]
|
||||||
|
readInput ls = case traverse (parse inputP "") ls of
|
||||||
|
Left e -> error (show e)
|
||||||
|
Right rs -> sort rs
|
||||||
|
|
||||||
|
splitRounds :: [Record] -> [[Record]]
|
||||||
|
splitRounds = split $ dropInitBlank $ keepDelimsL $ whenElt shiftBeginning
|
||||||
|
|
||||||
|
guardID :: Round -> GuardId
|
||||||
|
guardID ~(Record _ (BeginShift gID) : _) = gID
|
||||||
|
|
||||||
|
summarizeRounds :: [Round] -> (GuardId, Int, (Int, Int))
|
||||||
|
summarizeRounds rounds =
|
||||||
|
(guardID $ head rounds,
|
||||||
|
totalSleep rounds,
|
||||||
|
case M.assocs minMap of
|
||||||
|
[] -> (-1, 0)
|
||||||
|
xs -> maximumBy (compare `on` snd) xs)
|
||||||
|
where
|
||||||
|
getMin = todMin . localTimeOfDay . recTime
|
||||||
|
|
||||||
|
totalSleep = sum . map (sum . map (\[s,e] -> getMin e - getMin s) . chunksOf 2 . tail)
|
||||||
|
minMap =
|
||||||
|
foldl' (\a r ->
|
||||||
|
foldl' (\a' [s,e] ->
|
||||||
|
foldl' (\a'' m -> M.insertWith (+) m 1 a'') a' [getMin s .. (getMin e - 1)])
|
||||||
|
a (chunksOf 2 . tail $ r))
|
||||||
|
M.empty rounds
|
||||||
|
|
||||||
|
mostAsleep = maximumBy (compare `on` (\(_,t,_) -> t))
|
||||||
|
mostAsleepOnSameMinute = maximumBy (compare `on` (\(_,_,(_,m)) -> m))
|
||||||
|
|
||||||
|
main = do
|
||||||
|
rounds <- splitRounds . readInput . lines <$> getContents
|
||||||
|
let summary = map summarizeRounds . groupBy ((==) `on` guardID) . sortOn guardID $ rounds
|
||||||
|
putStrLn $ "Summary = " ++ show summary
|
||||||
|
putStrLn $ "Most asleep = " ++ show (mostAsleep summary)
|
||||||
|
putStrLn $ "Most asleep on same minute = " ++ show (mostAsleepOnSameMinute summary)
|
2
4/Setup.hs
Normal file
2
4/Setup.hs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import Distribution.Simple
|
||||||
|
main = defaultMain
|
4
4/stack.yaml
Normal file
4
4/stack.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
resolver: lts-12.21
|
||||||
|
|
||||||
|
packages:
|
||||||
|
- .
|
27
4/x4.cabal
Normal file
27
4/x4.cabal
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
-- Initial x4.cabal generated by cabal init. For further documentation,
|
||||||
|
-- see http://haskell.org/cabal/users-guide/
|
||||||
|
|
||||||
|
name: x4
|
||||||
|
version: 0.1.0.0
|
||||||
|
-- synopsis:
|
||||||
|
-- description:
|
||||||
|
license: BSD3
|
||||||
|
author: Abhinav Sarkar
|
||||||
|
maintainer: abhinav@abhinavsarkar.net
|
||||||
|
-- copyright:
|
||||||
|
-- category:
|
||||||
|
build-type: Simple
|
||||||
|
cabal-version: >=1.10
|
||||||
|
|
||||||
|
executable x4
|
||||||
|
main-is: 4.hs
|
||||||
|
-- other-modules:
|
||||||
|
-- other-extensions:
|
||||||
|
build-depends: base >=4.11 && <4.12
|
||||||
|
,split
|
||||||
|
,containers
|
||||||
|
,time
|
||||||
|
,parsec
|
||||||
|
ghc-options: -O2
|
||||||
|
-- hs-source-dirs:
|
||||||
|
default-language: Haskell2010
|
Loading…
Reference in New Issue
Block a user