-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathDay1.hs
38 lines (34 loc) · 1.4 KB
/
Day1.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
{-|
Module: Day1
Description: <https://adventofcode.com/2018/day/1 Day 1: Chronal Calibration>
-}
{-# LANGUAGE TransformListComp, TypeApplications #-}
module Day1 (day1a, day1b) where
import Control.Applicative ((<|>))
import Data.List (find, scanl', tails)
import Data.IntSet (empty, insert, member)
import Data.Maybe (listToMaybe)
import GHC.Exts (groupWith, sortWith)
parse :: String -> [Int]
parse = map (read . dropWhile (== '+')) . lines
day1a :: String -> Int
day1a = sum . parse
-- | Returns a repeat if found within a single cycle; otherwise, the running sums are grouped by the
-- | remainder modulus total sum, then the first smallest inter-group gap (if any) is returned.
day1b :: String -> Maybe Int
day1b input = beforeLoop <|> afterLoop
where list = scanl' (+) 0 $ parse input
beforeLoop = fmap fst . find (uncurry member) . zip list $ scanl (flip insert) empty list
total = last list
afterLoop = listToMaybe
[ endValue
| (n, z) <- zip @Int [0..] $ tail list
, then group by z `mod` total using groupWith
, (gap, startIndex, endValue) <-
[ (abs $ y - x, startIndex, endValue)
| (i, x):rest <- tails $ zip n z
, (j, y) <- rest
, let (startIndex, endValue) = if (total < 0) == (x < y) then (j, x) else (i, y)
]
, then sortWith by (gap, startIndex)
]