Browse Source

Solution for 4

Abhinav Sarkar 2 years ago
parent
commit
3a9e7f70aa
4 changed files with 118 additions and 0 deletions
  1. 85
    0
      4/4.hs
  2. 2
    0
      4/Setup.hs
  3. 4
    0
      4/stack.yaml
  4. 27
    0
      4/x4.cabal

+ 85
- 0
4/4.hs View File

@@ -0,0 +1,85 @@
1
+{-# LANGUAGE Strict #-}
2
+module Main where
3
+
4
+import Control.Applicative (some)
5
+import Data.Function (on)
6
+import Data.List (sort, foldl', maximumBy, groupBy, sortOn)
7
+import Data.List.Split (split, dropInitBlank, keepDelimsL, whenElt, chunksOf)
8
+import qualified Data.Map as M
9
+import Data.Time (LocalTime, diffUTCTime, localTimeToUTC, utc, todMin, localTimeOfDay)
10
+import Data.Time.Clock (NominalDiffTime)
11
+import Data.Time.Format (parseTimeOrError, defaultTimeLocale)
12
+import Text.Parsec
13
+
14
+type GuardId = Int
15
+data Action = BeginShift GuardId
16
+            | FallAsleep
17
+            | WakeUp
18
+            deriving (Show, Eq)
19
+data Record = Record { recTime :: LocalTime, recAction :: Action }
20
+              deriving (Show, Eq)
21
+type Round = [Record]
22
+
23
+shiftBeginning :: Record -> Bool
24
+shiftBeginning (Record _ (BeginShift _)) = True
25
+shiftBeginning _                         = False
26
+
27
+instance Ord Record where
28
+  compare = compare `on` recTime
29
+
30
+parseTime :: String -> LocalTime
31
+parseTime = parseTimeOrError False defaultTimeLocale "%F %R"
32
+
33
+diffLocalTime :: LocalTime -> LocalTime -> NominalDiffTime
34
+diffLocalTime a b = diffUTCTime (localTimeToUTC utc a) (localTimeToUTC utc b)
35
+
36
+inputP :: Parsec String () Record
37
+inputP = Record <$> (tsP <* space) <*> (bsP <|> wP <|> aP)
38
+  where
39
+    intP = read <$> some digit
40
+    tsP = parseTime <$> (char '[' *> some (noneOf "]") <* char ']')
41
+
42
+    bsP =  BeginShift
43
+          <$> (string "Guard" *> space *> char '#' *> intP <* space <* string "begins shift")
44
+
45
+    wP = WakeUp <$ string "wakes up"
46
+    aP = FallAsleep <$ string "falls asleep"
47
+
48
+readInput :: [String] -> [Record]
49
+readInput ls = case traverse (parse inputP "") ls of
50
+  Left e -> error (show e)
51
+  Right rs -> sort rs
52
+
53
+splitRounds :: [Record] -> [[Record]]
54
+splitRounds = split $ dropInitBlank $ keepDelimsL $ whenElt shiftBeginning
55
+
56
+guardID :: Round -> GuardId
57
+guardID ~(Record _ (BeginShift gID) : _) = gID
58
+
59
+summarizeRounds :: [Round] -> (GuardId, Int, (Int, Int))
60
+summarizeRounds rounds =
61
+  (guardID $ head rounds,
62
+   totalSleep rounds,
63
+   case M.assocs minMap of
64
+     [] -> (-1, 0)
65
+     xs -> maximumBy (compare `on` snd) xs)
66
+  where
67
+    getMin = todMin . localTimeOfDay . recTime
68
+    
69
+    totalSleep = sum . map (sum . map (\[s,e] -> getMin e - getMin s) . chunksOf 2 . tail)
70
+    minMap = 
71
+      foldl' (\a r ->
72
+              foldl' (\a' [s,e] ->
73
+                      foldl' (\a'' m -> M.insertWith (+) m 1 a'') a' [getMin s .. (getMin e - 1)])
74
+                     a (chunksOf 2 . tail $ r))
75
+             M.empty rounds
76
+
77
+mostAsleep = maximumBy (compare `on` (\(_,t,_) -> t))
78
+mostAsleepOnSameMinute = maximumBy (compare `on` (\(_,_,(_,m)) -> m))
79
+
80
+main = do
81
+  rounds <- splitRounds . readInput . lines <$> getContents
82
+  let summary = map summarizeRounds . groupBy ((==) `on` guardID) . sortOn guardID $ rounds
83
+  putStrLn $ "Summary = " ++ show summary
84
+  putStrLn $ "Most asleep = " ++ show (mostAsleep summary)
85
+  putStrLn $ "Most asleep on same minute = " ++ show (mostAsleepOnSameMinute summary)

+ 2
- 0
4/Setup.hs View File

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

+ 4
- 0
4/stack.yaml View File

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

+ 27
- 0
4/x4.cabal View File

@@ -0,0 +1,27 @@
1
+-- Initial x4.cabal generated by cabal init.  For further documentation,
2
+-- see http://haskell.org/cabal/users-guide/
3
+
4
+name:                x4
5
+version:             0.1.0.0
6
+-- synopsis:
7
+-- description:
8
+license:             BSD3
9
+author:              Abhinav Sarkar
10
+maintainer:          abhinav@abhinavsarkar.net
11
+-- copyright:
12
+-- category:
13
+build-type:          Simple
14
+cabal-version:       >=1.10
15
+
16
+executable x4
17
+  main-is:             4.hs
18
+  -- other-modules:
19
+  -- other-extensions:
20
+  build-depends:       base >=4.11 && <4.12
21
+                      ,split
22
+                      ,containers
23
+                      ,time
24
+                      ,parsec
25
+  ghc-options:        -O2
26
+  -- hs-source-dirs:
27
+  default-language:    Haskell2010

Loading…
Cancel
Save