Tidying
[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 where (State _ _ recipes) = head $ dropWhile (unfinished2 targetSeq) $ states state0
30
31 unfinished2 :: Recipes -> State -> Bool
32 unfinished2 target (State _ _ recipes) =
33 ((takeR (Q.length target) recipes) /= target)
34 &&
35 ((Q.take (Q.length target) (takeR (1 + Q.length target) recipes)) /= target)
36
37 states :: State -> [State]
38 states = iterate extend
39
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
44 total = v1 + v2
45 recipes' = if total >= 10
46 then recipes |> (total `div` 10) |> (total `mod` 10)
47 else recipes |> total
48 e1' = (e1 + v1 + 1) `mod` (Q.length recipes')
49 e2' = (e2 + v2 + 1) `mod` (Q.length recipes')
50
51 targetSeq :: Recipes
52 targetSeq = Q.fromList $ map read $ map (take 1 . drop 1) $ map show $ show targetLength
53
54 takeR n s = Q.drop (Q.length s - n) s