1 import qualified Data.Sequence as Q
2 import Data.Sequence ((<|), (|>))
4 import Data.Foldable (toList)
6 type Recipes = Q.Seq Int
7 data State = State Int Int Recipes deriving (Eq, Show)
10 -- targetLength = 59414
14 let state = State 0 1 (Q.fromList [3, 7])
15 putStrLn $ part1 state
18 part1 :: State -> String
19 part1 state0 = concatMap show $ toList $ Q.take 10 $ Q.drop targetLength recipes
20 where (State _ _ recipes) = last $ takeWhile unfinished1 $ states state0
22 unfinished1 :: State -> Bool
23 unfinished1 (State _ _ recipes) = (Q.length recipes) <= (targetLength + 10)
26 part2 state0 = if (takeR (Q.length targetSeq) recipes) == targetSeq
27 then (Q.length recipes) - (Q.length targetSeq)
28 else (Q.length recipes) - (Q.length targetSeq) - 1
29 where (State _ _ recipes) = head $ dropWhile (unfinished2 targetSeq) $ states state0
31 unfinished2 :: Recipes -> State -> Bool
32 unfinished2 target (State _ _ recipes) =
33 ((takeR (Q.length target) recipes) /= target)
35 ((Q.take (Q.length target) (takeR (1 + Q.length target) recipes)) /= target)
37 states :: State -> [State]
38 states = iterate extend
40 extend :: State -> State
41 extend (State e1 e2 recipes) = State e1' e2' recipes'
42 where v1 = Q.index recipes e1
43 v2 = Q.index recipes e2
45 recipes' = if total >= 10
46 then recipes |> (total `div` 10) |> (total `mod` 10)
48 e1' = (e1 + v1 + 1) `mod` (Q.length recipes')
49 e2' = (e2 + v2 + 1) `mod` (Q.length recipes')
52 targetSeq = Q.fromList $ map read $ map (take 1 . drop 1) $ map show $ show targetLength
54 takeR n s = Q.drop (Q.length s - n) s