diff options
Diffstat (limited to 'execs')
-rw-r--r-- | execs/Day14.hs | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/execs/Day14.hs b/execs/Day14.hs new file mode 100644 index 0000000..d82424a --- /dev/null +++ b/execs/Day14.hs | |||
@@ -0,0 +1,68 @@ | |||
1 | module Main where | ||
2 | |||
3 | import Utils | ||
4 | import Text.ParserCombinators.Parsec | ||
5 | import Text.Parsec.Char | ||
6 | import Data.Either | ||
7 | import Data.Char | ||
8 | import Data.Strings | ||
9 | import Numeric (showIntAtBase, readInt) | ||
10 | import Data.Map (Map) | ||
11 | import qualified Data.Map as Map | ||
12 | |||
13 | data Stmt = Mask String | Mem Int Int deriving Show | ||
14 | |||
15 | parseMask :: Parser Stmt | ||
16 | parseMask = string "mask = " >> Mask <$> many anyChar | ||
17 | |||
18 | parseMem :: Parser Stmt | ||
19 | parseMem = do | ||
20 | one <- string "mem[" >> many1 digit | ||
21 | two <- string "] = " >> many1 digit | ||
22 | return $ Mem (read one) (read two) | ||
23 | |||
24 | parseLine :: Parser Stmt | ||
25 | parseLine = try parseMask <|> parseMem | ||
26 | |||
27 | applyMask :: Int -> String -> Int | ||
28 | applyMask v m = fst $ head $ readInt 2 (`elem` "01") digitToInt wm | ||
29 | where bv = strPadLeft '0' 36 $ showIntAtBase 2 intToDigit v "" | ||
30 | wm = zipWith fn bv m | ||
31 | fn o 'X' = o | ||
32 | fn _ '1' = '1' | ||
33 | fn _ '0' = '0' | ||
34 | |||
35 | runProgram :: [Stmt] -> Int | ||
36 | runProgram ls = sum regs | ||
37 | where (mask, regs) = foldl fn ("", Map.empty) ls | ||
38 | fn (_, regs) (Mask s) = (s, regs) | ||
39 | fn (m, regs) (Mem idx val) = (m, Map.insert idx nval regs) | ||
40 | where nval = applyMask val m | ||
41 | |||
42 | floatings :: String -> [String] | ||
43 | floatings [] = [[]] | ||
44 | floatings ('X':xs) = floatings xs >>= (\b -> ['0':b, '1':b]) | ||
45 | floatings (x:xs) = map (x:) $ floatings xs | ||
46 | |||
47 | genIdxs :: Int -> String -> [Int] | ||
48 | genIdxs v m = map (fst . head . readInt 2 (`elem` "01") digitToInt) (floatings wm) | ||
49 | where bv = strPadLeft '0' 36 $ showIntAtBase 2 intToDigit v "" | ||
50 | wm = zipWith fn bv m | ||
51 | fn o '0' = o | ||
52 | fn _ '1' = '1' | ||
53 | fn _ 'X' = 'X' | ||
54 | |||
55 | v2chip :: [Stmt] -> Int | ||
56 | v2chip ls = sum regs | ||
57 | where (mask, regs) = foldl fn ("", Map.empty) ls | ||
58 | fn (_, regs) (Mask s) = (s, regs) | ||
59 | fn (m, regs) (Mem idx val) = (m, nmap) | ||
60 | where idxs = genIdxs idx m | ||
61 | nmap = flip Map.union regs $ Map.fromList $ zip idxs $ repeat val | ||
62 | |||
63 | |||
64 | main :: IO () | ||
65 | main = do | ||
66 | n <- rights . map (parse parseLine "main") . lines <$> readFile "input/14" | ||
67 | print $ runProgram n | ||
68 | print $ v2chip n | ||