87cbf3de8c38a443ed195335c403913e6af1edec
[advent-of-code-20.git] / advent15 / src / advent15.hs
1 -- import Debug.Trace
2
3 import Prelude hiding (round)
4 import Control.Monad
5 import Control.Monad.ST
6 import Data.STRef
7 import qualified Data.Vector.Unboxed.Mutable as V
8
9
10 main :: IO ()
11 main =
12 do let seed = [20, 0, 1, 11, 6, 3]
13 -- print seed
14 print $ part1 seed
15 print $ part2 seed
16
17
18 part1 seed = runGame seed 2020
19 part2 seed = runGame seed 30000000
20
21 zeroInt :: Int
22 zeroInt = 0
23
24 seedGame seed historySize =
25 do round <- newSTRef $ length seed
26 word <- newSTRef $ last seed
27 history <- V.replicate historySize zeroInt
28 forM_ (zip (init seed) [1..]) $ \(t, s) -> V.write history t s
29 return (round, word, history)
30
31 runGame seed roundsNeeded =
32 runST $
33 do (round, word, history) <- seedGame seed roundsNeeded
34 gameStep roundsNeeded round word history
35 readSTRef word
36
37 gameStep :: Int -> STRef s Int -> STRef s Int -> V.MVector s Int -> ST s ()
38 gameStep targetRound round word history =
39 do roundVal <- readSTRef round
40 if roundVal == targetRound
41 then return ()
42 else do
43 wordVal <- readSTRef word
44 wordH <- V.read history wordVal
45 let word' = speakWord wordH roundVal
46 V.write history wordVal roundVal
47 modifySTRef round (+1)
48 writeSTRef word word'
49 gameStep targetRound round word history
50
51
52 speakWord :: Int -> Int -> Int
53 speakWord 0 _ = 0
54 speakWord prev now = now - prev
55
56