import Control.Arrow import Control.Lens import Data.Function import Data.List import Data.List.Split import Data.Maybe import Text.Read type HASH = (String, Maybe Int) main :: IO () main = interact $ show . (day15a &&& day15b . parse) . init parse :: String -> [HASH] parse = map (second (readMaybe . tail) . break (`elem` "=-")) . splitOn "," day15a :: String -> Int day15a = sum . map (foldl' hashAlg 0) . splitOn "," day15b :: [HASH] -> Int day15b = sum . zipWith (*) [1 ..] . map (sum . zipWith (*) [1 ..] . map (fromJust . snd)) . foldl' processInstruction (replicate 256 []) hashAlg :: Int -> Char -> Int hashAlg x y = (17 * (fromEnum y + x)) `mod` 256 processInstruction :: [[HASH]] -> HASH -> [[HASH]] processInstruction bs (s, action) = (element box .~ l) bs where mInsert x = uncurry (++) . second (f x) . break (((==) `on` fst) x) f a (_:xs) = a : xs f a [] = [a] box = foldl' hashAlg 0 s newList = mInsert (s, action) (bs !! box) newDelList = deleteBy ((==) `on` fst) (s, action) (bs !! box) l = maybe newDelList (const newList) action