Start w
# (io, w) = stdio w
# ls = split ['\n'] $ read io
- = (sum $ 'DM'.elems $ one [] ls 'DM'.newMap)
+ = ( sum $ 'DM'.elems $ one [] ls 'DM'.newMap
+ , sum $ 'DM'.elems $ two [] ls 'DM'.newMap
+ )
toBin :: (Int -> [Char])
toBin = tob [35,34..0]
| n >= 2^b = ['1':tob bs (n-2^b)]
= ['0':tob bs n]
tob [] _ = []
-fromBin :: ([Char] -> Int)
-fromBin = foldr (\a b->a+2*b) 0 o map digitToInt
+fromBin :: [Char] -> Int
+fromBin rs= sum [n*2^i\\i<-[35,34..] & n <- map digitToInt rs]
one :: [Char] [[Char]] -> ((Map Int Int) -> Map Int Int)
one _ [['mask = ':mask]:xs] = one mask xs
msk 'X' c = c
one mask [[]:xs] = one mask xs
one mask [] = id
+
+two :: [Char] [[Char]] -> ((Map Int Int) -> Map Int Int)
+two _ [['mask = ':mask]:xs] = two mask xs
+two mask [['mem[':rest]:xs]
+ = case span isDigit rest of
+ (addr, ['] = ':val])
+ = foldl (o) (two mask xs)
+ [ 'DM'.put (fromBin addr) $ toInt $ toString val
+ \\addr<-mkAddrs $ zipWith aMask mask $ toBin $ toInt $ toString addr]
+where
+ aMask :: Char Char -> Char
+ aMask 'X' _ = 'X'
+ aMask '1' _ = '1'
+ aMask '0' c = c
+
+ mkAddrs :: [Char] -> [[Char]]
+ mkAddrs ['X':msk] = mkAddrs ['1':msk] ++ mkAddrs ['0':msk]
+ mkAddrs [c:msk] = map (\x->[c:x]) $ mkAddrs msk
+ mkAddrs [] = [[]]
+two mask [[]:xs] = two mask xs
+two mask [] = id