diff options
author | Marvin Borner | 2024-12-17 17:35:00 +0100 |
---|---|---|
committer | Marvin Borner | 2024-12-17 17:35:29 +0100 |
commit | 3f614a3bc0088ba727e9251df27a591b0d788da7 (patch) | |
tree | 040c2314cb1e86c65f75ce2c85d9a7ce38a9e7f3 /2024/17 | |
parent | ef5114bf2def85b351364c6e0de5f46e9a377d34 (diff) |
At least no 2d puzzle :)
Diffstat (limited to '2024/17')
-rw-r--r-- | 2024/17/solve.hs | 60 |
1 files changed, 32 insertions, 28 deletions
diff --git a/2024/17/solve.hs b/2024/17/solve.hs index 45a3cdc..5bcaf0b 100644 --- a/2024/17/solve.hs +++ b/2024/17/solve.hs @@ -6,11 +6,11 @@ import Control.Monad.State ( State , modify ) import Data.Bits ( (.&.) + , shiftL , xor ) import Data.Functor ( (<&>) ) import Data.Void -import Debug.Trace import Prelude hiding ( (||) ) import Text.Megaparsec hiding ( Pos , State @@ -35,24 +35,18 @@ type Parser = Parsec Void String type ST = State Registers register :: Parser Int -register = do - string "Register " - reg <- oneOf "ABC" - string ": " - L.decimal <* some (char '\n') +register = + string "Register " *> oneOf "ABC" *> string ": " *> L.decimal <* char '\n' program :: Parser Program -program = do - string "Program: " - many $ L.decimal <* optional (char ',') +program = string "Program: " *> L.decimal `sepBy` char ',' input :: Parser (Registers, Program) input = do - regs <- - Registers <$> register <*> register <*> register <*> pure 0 <*> pure Nothing - prog <- program - many $ char '\n' - return (regs, prog) + regs <- Registers <$> register <*> register <*> register + char '\n' + prog <- program <* many (char '\n') + return (regs 0 Nothing, prog) combo :: Int -> ST Int combo x | x <= 3 = return x @@ -93,25 +87,35 @@ evalInstruction 7 x = do modify $ \s -> s { c = numerator `div` denominator } eval :: Program -> ST Out -eval is = do - ip <- gets pc - if ip + 1 > length is - then return [] - else do - evalInstruction (is !! ip) (is !! (ip + 1)) - ip' <- gets pc -- jumped? - mx <- gets out - modify $ \s -> s { out = Nothing, pc = if ip == ip' then ip + 2 else ip' } - next <- eval is - return $ case mx of - Just x -> x : next - Nothing -> next +eval is = gets pc >>= \case + ip | ip + 1 > length is -> return [] + ip -> do + evalInstruction (is !! ip) (is !! (ip + 1)) + ip' <- gets pc -- jumped? + mx <- gets out + modify $ \s -> s { out = Nothing, pc = if ip == ip' then ip + 2 else ip' } + next <- eval is + return $ case mx of + Just x -> x : next + Nothing -> next + +rev :: Registers -> Program -> [Int] +rev regs prog = go [0] prog + where + go z [] = z + go z (x : xs) = do + val <- go z xs + off <- [0 .. 7] + let try = val `shiftL` 3 + off + case evalState (eval prog) (regs { a = try }) of + h : _ | h == x -> return try + _ -> empty main :: IO () main = do f <- readFile "input" case runParser (input <* eof) "" f of Right (regs, prog) -> do - print prog print $ evalState (eval prog) regs + print $ rev regs prog Left err -> putStrLn $ errorBundlePretty err |