aoc2020/15.hs

39 lines
1.0 KiB
Haskell

import qualified Data.Map.Strict as Map
import Data.Map.Strict (Map)
import Debug.Trace
import Control.Monad.State
-- 1st is turn number
-- 2nd is map of spoken
-- 3rd is next number to speak
type S = (Int, Map Int Int, Int)
produceInitial lst =
let len = length lst
f acc (idx, el) = Map.insert el idx acc
initMap = foldl f Map.empty $ zip [0..] lst
in (len, initMap, 0)
speak :: Int -> State S Int
speak n = do
(turn, spoken, nextSpeak) <- get
let lastSpoke = Map.lookup nextSpeak spoken
let spoken2 = Map.insert nextSpeak turn spoken
let nextSpeak2 = case lastSpoke of
Nothing -> 0
Just n -> turn - n
let result = (turn + 1, spoken2, nextSpeak2)
-- modify (\_ -> traceShow result result)
modify (\_ -> result)
return nextSpeak
speakStream lst = (++) lst $ flip evalState initial $ mapM speak [0..]
where initial = produceInitial lst
actualInput = [5,1,9,18,13,8,0]
exInput = [0,3,6]
n = 30000000
-- n = 2020
main = do print (speakStream actualInput !! (n-1))