40 lines
1.1 KiB
Haskell
40 lines
1.1 KiB
Haskell
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
|