Day 17: Chronospatial Computer
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
Haskell
Woah, that was suddenly a hard one: several tricky things combined. I’m not a big fan of the kind of problems like part 2 today, but eh - you can’t please everyone.
Solution
import Control.Monad import Control.Monad.RWS import Data.Bits import Data.Foldable import Data.List import Data.List.Split import Data.Vector (Vector) import Data.Vector qualified as Vector type Machine = RWS (Vector Int) [Int] (Int, Int, Int) readInput :: String -> ((Int, Int, Int), Vector Int) readInput s = let (regs, _ : [prog]) = break null $ lines s in ( let [a, b, c] = map (read . last . words) regs in (a, b, c), let [_, s] = words prog in Vector.fromList $ map read $ splitOn "," s ) stepMachine :: Int -> Machine Int stepMachine ip = do opcode <- asks (Vector.! ip) operand <- asks (Vector.! (ip + 1)) (a, b, c) <- get let combo = [0, 1, 2, 3, a, b, c, undefined] !! operand ip' = ip + 2 adv = a `div` (2 ^ combo) store 'A' v = modify (\(_, b, c) -> (v, b, c)) store 'B' v = modify (\(a, _, c) -> (a, v, c)) store 'C' v = modify (\(a, b, _) -> (a, b, v)) case opcode of 0 -> store 'A' adv >> return ip' 1 -> store 'B' (b `xor` operand) >> return ip' 2 -> store 'B' (combo .&. 7) >> return ip' 3 -> return $ if a == 0 then ip' else operand 4 -> store 'B' (b `xor` c) >> return ip' 5 -> tell [combo .&. 7] >> return ip' 6 -> store 'B' adv >> return ip' 7 -> store 'C' adv >> return ip' part1 (regs, prog) = let (a, s, w) = runRWS (go 0) prog regs in intercalate "," $ map show w where go ip = when (ip < Vector.length prog) $ stepMachine ip >>= go part2 (_, prog) = minimum $ foldM go 0 $ reverse $ toList prog where go a d = do b <- [0 .. 7] let a' = (a `shiftL` 3) .|. b b1 = b `xor` 5 b2 = b1 `xor` (a' `shiftR` b1) b3 = b2 `xor` 6 guard $ b3 .&. 7 == d return a' main = do input <- readInput <$> readFile "input17" putStrLn $ part1 input print $ part2 input