-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy path15.hs
48 lines (41 loc) · 1.39 KB
/
15.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
import Data.Char (ord)
import Control.Arrow ((&&&))
main :: IO ()
main = interact $ (++ "\n") . show . (p1 &&& p2) . steps . lines
steps :: [String] -> [String]
steps = concatMap f
where
f [] = []
f s = let (a, b) = span (/= ',') s in a : f (drop 1 b)
p1 :: [String] -> Int
p1 = sum . map hash
hash :: String -> Int
hash = foldl (\v c -> (v + (ord c)) * 17 `mod` 256) 0
type Lens = (String, Int)
data Op = Remove String | Replace Lens
type Step = (Op, Int)
decode :: String -> Step
decode s = case break (`elem` "-=") s of
(a, '-':b) -> (Remove a, hash a)
(a, '=':b) -> (Replace (a, read b), hash a)
p2 :: [String] -> Int
p2 = power . foldl f boxes . map decode
where
boxes = take 256 $ repeat []
f bs = (`modify` bs)
modify step = zipWith (modifyBox step) [0..]
modifyBox (op, si) i box
| si == i = modifyBox' op box
| otherwise = box
modifyBox' (Remove label) = filter ((/= label) . fst)
modifyBox' (Replace lens) = reverse . append . foldl g (Just lens, [])
where
g (Nothing, box) lens' = (Nothing, lens' : box)
g (Just lens, box) lens'
| (fst lens) == (fst lens') = (Nothing, lens : box)
| otherwise = (Just lens, lens' : box)
append (Nothing, box) = box
append (Just lens, box) = lens : box
power = sum . zipWith pb [1..]
pb i = sum . zipWith (p i) [1..]
p i j (_, v) = i * j * v