-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay14.hs
68 lines (58 loc) · 2.18 KB
/
Day14.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
-- Day 14: Chocolate Charts
--
-- Usage:
--
-- ghc -O2 Day14.hs
-- ./Day14.hs <input>
import Control.Monad ( liftM2 )
import Data.Sequence ( Seq(Empty, (:|>))
, (><)
, (|>)
)
import qualified Data.Sequence as S
import Prelude hiding ( seq )
import System.Environment ( getArgs )
type Score = Int
type Scoreboard = (Seq Score, Int, Int)
digits :: Integral x => x -> Seq x
digits 0 = S.fromList [0]
digits n = digits' n
where
digits' 0 = Empty
digits' x = digits' (x `div` 10) |> x `mod` 10
rightMatches :: Eq a => Seq a -> Seq a -> Bool
rightMatches Empty _ = True
rightMatches _ Empty = False
rightMatches (xs :|> a) (ys :|> b) | a /= b = False
| otherwise = rightMatches xs ys
rightMatchesOffset :: (Eq a) => Seq a -> Seq a -> Bool
rightMatchesOffset patt (ys :|> _) = rightMatches patt ys
rightMatchesOffset patt seq = rightMatches patt seq
generateRecipes :: Scoreboard -> (Seq Score -> Bool) -> Scoreboard
generateRecipes (scores, elf1, elf2) haltTest
| haltTest scores' = (scores', elf1', elf2')
| otherwise = generateRecipes (scores', elf1', elf2') haltTest
where
elf1' = mod (elf1 + recipe1 + 1) (length scores')
elf2' = mod (elf2 + recipe2 + 1) (length scores')
scores' = scores >< digits (recipe1 + recipe2)
recipe1 = S.index scores elf1
recipe2 = S.index scores elf2
initialScoreboard :: Scoreboard
initialScoreboard = (S.fromList [3, 7], 0, 1)
part1 :: Int -> Seq Score
part1 x = S.take 10 $ S.drop x scores
where
(scores, _, _) = generateRecipes initialScoreboard countReached
countReached seq = length seq > (x + 10)
part2 :: Int -> Int
part2 x = length scores - length patt
where
(scores, _, _) = generateRecipes initialScoreboard matches
matches = liftM2 (||) (rightMatches patt) (rightMatchesOffset patt)
patt = digits x
main :: IO ()
main = do
[input] <- fmap (map read) getArgs
print $ part1 input
print $ part2 input