aboutsummaryrefslogtreecommitdiff
path: root/execs/Day14.hs
diff options
context:
space:
mode:
Diffstat (limited to 'execs/Day14.hs')
-rw-r--r--execs/Day14.hs68
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 @@
1module Main where
2
3import Utils
4import Text.ParserCombinators.Parsec
5import Text.Parsec.Char
6import Data.Either
7import Data.Char
8import Data.Strings
9import Numeric (showIntAtBase, readInt)
10import Data.Map (Map)
11import qualified Data.Map as Map
12
13data Stmt = Mask String | Mem Int Int deriving Show
14
15parseMask :: Parser Stmt
16parseMask = string "mask = " >> Mask <$> many anyChar
17
18parseMem :: Parser Stmt
19parseMem = do
20 one <- string "mem[" >> many1 digit
21 two <- string "] = " >> many1 digit
22 return $ Mem (read one) (read two)
23
24parseLine :: Parser Stmt
25parseLine = try parseMask <|> parseMem
26
27applyMask :: Int -> String -> Int
28applyMask 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
35runProgram :: [Stmt] -> Int
36runProgram 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
42floatings :: String -> [String]
43floatings [] = [[]]
44floatings ('X':xs) = floatings xs >>= (\b -> ['0':b, '1':b])
45floatings (x:xs) = map (x:) $ floatings xs
46
47genIdxs :: Int -> String -> [Int]
48genIdxs 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
55v2chip :: [Stmt] -> Int
56v2chip 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
64main :: IO ()
65main = do
66 n <- rights . map (parse parseLine "main") . lines <$> readFile "input/14"
67 print $ runProgram n
68 print $ v2chip n