diff options
author | tomsmeding <tom.smeding@gmail.com> | 2017-12-18 10:21:30 +0100 |
---|---|---|
committer | tomsmeding <tom.smeding@gmail.com> | 2017-12-18 10:21:30 +0100 |
commit | fb60a0cb672535dc06e2a64088eebae2fb50bedb (patch) | |
tree | 8dccd3a4ca9f06ac8a1bca4b0bff599fd49bdbe7 | |
parent | 53c0e9c38422f3cd5cf567bd8a7d2a8cdae66be8 (diff) |
Day 18
I misread part 2 thinking that 'rcv 0' still shouldn't do anything.
It should. That solved some problems. As in, let it work first try
afterwards.
-rw-r--r-- | 2017/18.hs | 84 | ||||
-rw-r--r-- | 2017/18.in | 41 |
2 files changed, 125 insertions, 0 deletions
diff --git a/2017/18.hs b/2017/18.hs new file mode 100644 index 0000000..a803906 --- /dev/null +++ b/2017/18.hs @@ -0,0 +1,84 @@ +import Control.Monad +import Data.Char +import Data.Maybe +import qualified Data.Map.Strict as Map + +data Ref = Reg Char | Num Int + deriving Show + +data Ins = Set Char Ref | Add Char Ref | Mul Char Ref | Mod Char Ref | Snd Ref | Rcv Char | Jgz Ref Ref + deriving Show + +parseRef :: String -> Ref +parseRef str = if all (\c -> isDigit c || c == '-') str then Num (read str) else Reg (head str) + +parse :: String -> Ins +parse str = case words str of + ["set", [d], s] -> Set d (parseRef s) + ["add", [d], s] -> Add d (parseRef s) + ["mul", [d], s] -> Mul d (parseRef s) + ["mod", [d], s] -> Mod d (parseRef s) + ["snd", r] -> Snd (parseRef r) + ["rcv", [d]] -> Rcv d + ["jgz", c, t] -> Jgz (parseRef c) (parseRef t) + _ -> undefined + +get :: Ref -> Map.Map Char Int -> Int +get (Num i) _ = i +get (Reg c) vmap = fromMaybe 0 (Map.lookup c vmap) + +exec1 :: [Ins] -> Int +exec1 inss' = go inss' 0 Map.empty 0 + where + go :: [Ins] -> Int -> Map.Map Char Int -> Int -> Int + go inss idx vmap snd + | idx < 0 = undefined + | idx >= length inss = undefined + | otherwise = case inss !! idx of + Set d ref -> go inss (idx+1) (Map.insert d (get ref vmap) vmap) snd + Add d ref -> go inss (idx+1) (Map.insert d (get (Reg d) vmap + get ref vmap) vmap) snd + Mul d ref -> go inss (idx+1) (Map.insert d (get (Reg d) vmap * get ref vmap) vmap) snd + Mod d ref -> go inss (idx+1) (Map.insert d (get (Reg d) vmap `mod` get ref vmap) vmap) snd + Snd ref -> go inss (idx+1) vmap (get ref vmap) + Rcv d -> if get (Reg d) vmap == 0 then go inss (idx+1) vmap snd else snd + Jgz cd tg -> go inss (idx + if get cd vmap > 0 then get tg vmap else 1) vmap snd + +data State = State [Ins] Int (Map.Map Char Int) [Int] + deriving Show + +makeState :: [Ins] -> Int -> State +makeState inss pid = State inss 0 (Map.fromList [('p', pid)]) [] + +supplyInput :: State -> [Int] -> State +supplyInput (State inss idx vmap inp) input = State inss idx vmap (inp ++ input) + +exec2 :: State -> (State, [Int]) +exec2 state@(State inss idx vmap inp) + | idx < 0 = (state, []) + | idx >= length inss = (state, []) + | otherwise = case inss !! idx of + Set d ref -> exec2 $ State inss (idx+1) (Map.insert d (get ref vmap) vmap) inp + Add d ref -> exec2 $ State inss (idx+1) (Map.insert d (get (Reg d) vmap + get ref vmap) vmap) inp + Mul d ref -> exec2 $ State inss (idx+1) (Map.insert d (get (Reg d) vmap * get ref vmap) vmap) inp + Mod d ref -> exec2 $ State inss (idx+1) (Map.insert d (get (Reg d) vmap `mod` get ref vmap) vmap) inp + Snd ref -> fmap (get ref vmap :) $ exec2 $ State inss (idx+1) vmap inp + Rcv d -> case inp of + [] -> (state, []) + x:xs -> exec2 $ State inss (idx+1) (Map.insert d x vmap) xs + Jgz cd tg -> exec2 $ State inss (idx + if get cd vmap > 0 then get tg vmap else 1) vmap inp + +parallel :: State -> State -> Int +parallel state0 state1 = + let (state0', out0) = exec2 state0 + (state1', out1) = exec2 (supplyInput state1 out0) + state0'' = supplyInput state0' out1 + in if null out0 && null out1 + then 0 + else length out1 + parallel state0'' state1' + +main :: IO () +main = do + input <- liftM (map parse . lines) (readFile "18.in") + print (exec1 input) + + print $ parallel (makeState input 0) (makeState input 1) diff --git a/2017/18.in b/2017/18.in new file mode 100644 index 0000000..8b74206 --- /dev/null +++ b/2017/18.in @@ -0,0 +1,41 @@ +set i 31 +set a 1 +mul p 17 +jgz p p +mul a 2 +add i -1 +jgz i -2 +add a -1 +set i 127 +set p 735 +mul p 8505 +mod p a +mul p 129749 +add p 12345 +mod p a +set b p +mod b 10000 +snd b +add i -1 +jgz i -9 +jgz a 3 +rcv b +jgz b -1 +set f 0 +set i 126 +rcv a +rcv b +set p a +mul p -1 +add p b +jgz p 4 +snd a +set a b +jgz 1 3 +snd b +set f 1 +add i -1 +jgz i -11 +snd a +jgz f -16 +jgz a -19 |