Done day 15
[advent-of-code-20.git] / advent15 / src / advent15.hs
diff --git a/advent15/src/advent15.hs b/advent15/src/advent15.hs
new file mode 100644 (file)
index 0000000..87cbf3d
--- /dev/null
@@ -0,0 +1,56 @@
+-- import Debug.Trace
+
+import Prelude hiding (round)
+import Control.Monad
+import Control.Monad.ST
+import Data.STRef
+import qualified Data.Vector.Unboxed.Mutable as V
+
+
+main :: IO ()
+main = 
+  do  let seed = [20, 0, 1, 11, 6, 3]
+      -- print seed
+      print $ part1 seed
+      print $ part2 seed
+
+
+part1 seed = runGame seed 2020
+part2 seed = runGame seed 30000000
+
+zeroInt :: Int
+zeroInt = 0
+
+seedGame seed historySize = 
+  do round <- newSTRef $ length seed
+     word <- newSTRef $ last seed
+     history <- V.replicate historySize zeroInt
+     forM_ (zip (init seed) [1..]) $ \(t, s) -> V.write history t s
+     return (round, word, history)
+
+runGame seed roundsNeeded =
+  runST $ 
+    do (round, word, history) <- seedGame seed roundsNeeded
+       gameStep roundsNeeded round word history
+       readSTRef word
+
+gameStep :: Int -> STRef s Int -> STRef s Int -> V.MVector s Int -> ST s ()
+gameStep targetRound round word history =
+  do roundVal <- readSTRef round
+     if roundVal == targetRound
+     then return ()
+     else do 
+           wordVal <- readSTRef word
+           wordH <- V.read history wordVal
+           let word' = speakWord wordH roundVal
+           V.write history wordVal roundVal
+           modifySTRef round (+1)
+           writeSTRef word word'
+           gameStep targetRound round word history
+
+
+speakWord :: Int -> Int -> Int
+speakWord 0 _ = 0
+speakWord prev now = now - prev
+
+