Day 14
[advent-of-code-18.git] / src / advent14 / advent14.hs
1 import qualified Data.Sequence as Q
2 import Data.Sequence ((<|), (|>))
3 import Data.List
4 import Data.Foldable (toList)
5
6 type Recipes = Q.Seq Int
7 data State = State Int Int Recipes deriving (Eq, Show)
8
9 targetLength = 327901
10 -- targetLength = 59414
11
12 main :: IO ()
13 main = do
14 let state = State 0 1 (Q.fromList [3, 7])
15 putStrLn $ part1 state
16 print $ part2 state
17
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
21
22 unfinished1 :: State -> Bool
23 unfinished1 (State _ _ recipes) = (Q.length recipes) <= (targetLength + 10)
24
25 part2 :: State -> Int
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 -- recipes -- (Q.length recipes) - (Q.length targetSeq)
30
31 where (State _ _ recipes) = head $ dropWhile (unfinished2 targetSeq) $ states state0
32
33 unfinished2 :: Recipes -> State -> Bool
34 unfinished2 target (State _ _ recipes) =
35 ((takeR (Q.length target) recipes) /= target)
36 &&
37 ((Q.take (Q.length target) (takeR (1 + Q.length target) recipes)) /= target)
38
39 states :: State -> [State]
40 states = iterate extend
41
42 extend :: State -> State
43 extend (State e1 e2 recipes) = State e1' e2' recipes'
44 where v1 = Q.index recipes e1
45 v2 = Q.index recipes e2
46 total = v1 + v2
47 recipes' = if total >= 10
48 then recipes |> (total `div` 10) |> (total `mod` 10)
49 else recipes |> total
50 e1' = (e1 + v1 + 1) `mod` (Q.length recipes')
51 e2' = (e2 + v2 + 1) `mod` (Q.length recipes')
52
53 targetSeq :: Recipes
54 targetSeq = Q.fromList $ map read $ map (take 1 . drop 1) $ map show $ show targetLength
55
56 takeR n s = Q.drop (Q.length s - n) s