Solution for 4

master
Abhinav Sarkar 2018-12-07 10:25:21 +05:30
förälder 3b10150e08
incheckning 3a9e7f70aa
4 ändrade filer med 118 tillägg och 0 borttagningar

85
4/4.hs Normal file
Visa fil

@ -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
Visa fil

@ -0,0 +1,2 @@
import Distribution.Simple
main = defaultMain

4
4/stack.yaml Normal file
Visa fil

@ -0,0 +1,4 @@
resolver: lts-12.21
packages:
- .

27
4/x4.cabal Normal file
Visa fil

@ -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