-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay11.hs
50 lines (43 loc) · 1.57 KB
/
Day11.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
module Day11
( part1
, part2
) where
import Data.ByteString (ByteString)
import Data.Either (fromRight)
import Data.MultiSet as MS (MultiSet, distinctElems,
distinctSize, empty,
fromList, insertMany, occur,
size)
import Helpers.Parsers.ByteString (Parser, decimal)
import Text.Megaparsec (eof, manyTill, parse)
import Text.Megaparsec.Byte (eol)
type Stones = MultiSet Int
parseInput :: Parser Stones
parseInput = fromList <$> manyTill decimal eol
blink :: Stones -> Stones
blink stones = foldr (collatz stones) empty . distinctElems $ stones
collatz :: Stones -> Int -> Stones -> Stones
collatz stones stone stones'
| stone == 0 = insertMany 1 count stones'
| even splitter = foldr (`insertMany` count) stones' split
| otherwise = insertMany (2024 * stone) count stones'
where
count = occur stone stones
splitter = ceiling . logBase 10 . fromIntegral $ (stone + 1)
split = [stone `mod` 10 ^ div splitter 2, stone `div` 10 ^ div splitter 2]
part1 :: Bool -> ByteString -> String
part1 _ =
show
. size
. (!! 25)
. iterate blink
. fromRight (error "input could not be parsed")
. parse parseInput "day11"
part2 :: Bool -> ByteString -> String
part2 _ =
show
. size
. (!! 75)
. iterate blink
. fromRight (error "input could not be parsed")
. parse parseInput "day11"