This repository has been archived by the owner on Nov 17, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 8
/
Day15.hs
61 lines (55 loc) · 1.59 KB
/
Day15.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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
-- |
-- Module : AOC.Challenge.Day15
-- License : BSD3
--
-- Stability : experimental
-- Portability : non-portable
--
-- Day 15. See "AOC.Solver" for the types used in this module!
module AOC.Challenge.Day15 (
day15a
, day15b
) where
import AOC.Solver ((:~>)(..))
import Control.Monad.Loops (whileM_)
import Control.Monad.ST (runST)
import Control.Monad.State.Strict (evalStateT, get, gets, put)
import Data.Foldable (for_)
import Data.List.Split (splitOn)
import GHC.Int (Int32)
import Text.Read (readMaybe)
import qualified Data.Vector.Unboxed.Mutable as MV
day15a :: [Int] :~> Int
day15a = MkSol
{ sParse = traverse readMaybe . splitOn ","
, sShow = show
, sSolve = Just . looper 2020
}
day15b :: [Int] :~> Int
day15b = MkSol
{ sParse = sParse day15a
, sShow = show
, sSolve = Just . looper 30000000
}
data LoopState = LS
{ lsLastSaid :: !Int
, lsCurrTime :: !Int32
}
looper :: Int -> [Int] -> Int
looper n xs0 = runST $ flip evalStateT (LS 0 0) $ do
v <- MV.replicate n 0
for_ xs0 $ \y -> do
LS x i <- get
MV.unsafeWrite v x i
put (LS y (i + 1))
whileM_ (gets ((< n32) . lsCurrTime)) $ do
LS x i <- get
lst <- MV.unsafeRead v x
MV.unsafeWrite v x i
let j | lst == 0 = 0
| otherwise = i - lst
put (LS (fromIntegral j) (i + 1))
gets lsLastSaid
where
n32 :: Int32
n32 = fromIntegral n