aoc2022/day11ungolfed.hs
2022-12-11 14:34:28 +01:00

75 lines
2.2 KiB
Haskell

import Control.Monad.State.Strict
import Data.List
data Monkey = Monkey {items :: [Int], operation :: Int -> Int, test :: (Int, Int, Int), inspected :: Int}
op :: String -> Int -> Int -> Int
op "*" = (*)
op "+" = (+)
pread "old" old = old
pread i _ = read i
parseOp :: [String] -> Int -> Int
parseOp [a,o,b] = \old -> op o (pread a old) (pread b old)
parseDiv :: String -> Int
parseDiv = read.last.words
parse [_,i,o,d,t,f] = Monkey (read$"["++drop 18 i++"]")(parseOp $ words$drop 19 o) (parseDiv d, parseDiv t, parseDiv f) 0
instance Show Monkey where
show (Monkey i o t ins) = "Monkey {items = " ++ show i ++ "} ("++ show ins ++")"
instance Eq Monkey where
m1 == m2 = inspected m1 == inspected m2
instance Ord Monkey where
m1<=m2 = inspected m1 <= inspected m2
type MState = [Monkey]
extract :: Int -> [a] -> ([a], a, [a])
extract i m|(f,(c:b))<-splitAt i m=(f,c,b)
addTo :: Int -> Int -> State MState ()
addTo monkeyId item = do
monkeys <- get
let (f,monkey,b) = extract monkeyId monkeys
let newMonkey = monkey {items = items monkey ++ [item]}
put $ f ++ (newMonkey:b)
step :: (Int -> Int) -> Int -> State MState ()
step op monkeyId = do
monkeys <- get
let monkey = monkeys !! monkeyId
let newInspected = inspected monkey + length (items monkey)
forM_ (items monkey) $ \item -> do
let new = operation monkey item
let unworried = op new
let (divis, mtrue, mfalse) = test monkey
if unworried `mod` divis == 0
then addTo mtrue unworried
else addTo mfalse unworried
let newMonkey = monkey {items = [], inspected = newInspected}
m <- get
let (f,c,b) = extract monkeyId m
put (f ++ (newMonkey:b))
monkeyRound :: (Int -> Int) -> State MState ()
monkeyRound op = do
l <- length<$>get
forM_ [0..l-1] $ step op
monkeyRounds i op = do
forM_ [1..i] $ \_-> monkeyRound op
maxdivis = product.map((\(a,b,c)->a).test)
compute monkeys n op = product $ map inspected$ take 2$reverse$sort$execState (monkeyRounds n op) monkeys
main = do
monkeyFile <- map (parse.filter (/="")).groupBy(const (/="")).lines<$>readFile "day11long"
print $ compute monkeyFile 20 (`div` 3)
print $ compute monkeyFile 10000 (`mod` (maxdivis monkeyFile))