-
Notifications
You must be signed in to change notification settings - Fork 0
/
day9.hs
36 lines (31 loc) · 1.64 KB
/
day9.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
import Data.Map (Map, (!))
import qualified Data.Map.Strict as Map
type Circle = Map Int (Int, Int)
type State = (Circle, Int, Map Int Int)
turn :: State -> (Int, Int) -> State
turn (circle, current, scores) (player, number)
| number `mod` 23 == 0 =
let removed = iterate (fst . (circle !)) current !! 7
(Just (left, right), circle') = Map.updateLookupWithKey (const (const Nothing)) removed circle
circle'' = Map.insertWithKey updateRight left (0, right) $ Map.insertWithKey updateLeft right (left, 0) circle'
score = number + removed
in (circle'', right, Map.insertWith (+) player score scores)
| otherwise =
let left = snd $ circle ! current
(Just (_, right), circle') = Map.insertLookupWithKey updateRight left (0, number) circle
circle'' = Map.insert number (left, right) $ Map.insertWithKey updateLeft right (number, 0) circle'
in (circle'', number, scores)
where updateLeft _ (left, _) (_, right) = (left, right)
updateRight _ (_, right) (left, _) = (left, right)
parse :: [String] -> (Int, Int)
parse [players, "players;", "last", "marble", "is", "worth", marbles, "points"] = (read players, read marbles)
part1 :: String -> Int
part1 input =
let (players, marbles) = parse $ words input
(_, _, scores) = foldl turn (Map.fromList [(0, (0, 0))], 0, Map.empty) $ zip (cycle [1..players]) [1..marbles]
in maximum $ Map.elems scores
part2 :: String -> Int
part2 input =
let (players, marbles) = parse $ words input
(_, _, scores) = foldl turn (Map.fromList [(0, (0, 0))], 0, Map.empty) $ zip (cycle [1..players]) [1..marbles * 100]
in maximum $ Map.elems scores