-
Notifications
You must be signed in to change notification settings - Fork 0
/
Day11.hs
executable file
·57 lines (51 loc) · 1.76 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
51
52
53
54
55
56
57
#!/usr/bin/env stack
{-
stack script
--resolver lts-20.2
--package microlens
--package split
-}
import Data.List
import Data.List.Split
import Lens.Micro
data Monkey = Monkey {
itemUpdate :: Int -> Int,
itemCheck :: Int,
sendTrue :: Int,
sendFalse :: Int
}
parseMonkey :: String -> ([Int], Monkey)
parseMonkey s =
let ls = lines s
lastInt = read . last . splitOn " "
op ["old", "*"] = (^ 2)
op [n, "*"] = (* read n)
op l = (+) . read . head $ l
in (
fmap read . splitOn ", " . drop 1 . dropWhile (/=':') $ ls!!1,
Monkey {
itemUpdate = op . take 2 . reverse . splitOn " " $ (ls!!2),
itemCheck = lastInt (ls!!3),
sendTrue = lastInt (ls!!4),
sendFalse = lastInt (ls!!5)
}
)
processMonkey :: (Int -> Int) -> Monkey -> [Int] -> ([Int], [Int])
processMonkey op m = partition (\v -> v `rem` itemCheck m == 0) . fmap (op . itemUpdate m)
processRound :: (Int -> Int) -> [Monkey] -> [(Int, [Int])] -> [(Int, [Int])]
processRound op ms state = foldl update state (zip [0..] ms)
where
update :: [(Int, [Int])] -> (Int, Monkey) -> [(Int, [Int])]
update s (i, m) =
let (n, c) = s!!i
(pass, fail) = processMonkey op m c
in (s & ix i .~ (n + length c, []) & ix (sendTrue m) . _2 %~ (++pass) & ix (sendFalse m) . _2 %~ (++fail))
main :: IO ()
main = do
input <- readFile "data/11.txt"
let input' = fmap parseMonkey . splitOn "\n\n" $ input
let (initialState, monkeys) = unzip input' & _1 %~ fmap (0,)
let score = product . take 2 . reverse . sort
print . score . fmap fst . (!! 20) . iterate (processRound (`div` 3) monkeys) $ initialState
let range = foldl1 lcm (fmap itemCheck monkeys)
print . score . fmap fst . (!! 10000) . iterate (processRound (`mod` range) monkeys) $ initialState