5 from Data.IntMap.Strict import :: IntMap
6 import qualified Data.IntMap.Strict as DM
8 input = [6,13,1,15,2,0]
13 one = speak 2020 input
14 two = speak 30000000 input
17 //speak :: Int [Int] -> Int
18 //speak num inp = speak` num (reverse inp)
20 // speak` 0 spoken = spoken!!length inp
21 // speak` idx [ls:spoken] = case [i\\i<-[0..] & s<-spoken | s == ls] of
22 // [] = speak` (idx-1) [0,ls:spoken]
23 // [i:_] = speak` (idx-1) [i+1,ls:spoken]
25 speak :: Int [Int] -> Int
26 speak num inp = speak` (length inp) (last inp)
27 ('DM'.fromList [(num, idx)\\idx<-[0..] & num <-init inp])
29 speak` :: !Int !Int !(IntMap Int) -> Int
30 speak` idx last spoken
32 = speak` (idx+1) (maybe 0 (\i->idx-i-1) ('DM'.get last spoken)) ('DM'.put last (idx-1) spoken)