Signed-off-by: Amneesh Singh <natto@weirdnatto.in>
This commit is contained in:
2024-12-17 19:45:02 +05:30
parent bf7442bd42
commit 54f512a51f
2 changed files with 93 additions and 0 deletions

View File

@@ -129,3 +129,9 @@ executable day16
hs-source-dirs: src hs-source-dirs: src
main-is: Day16.hs main-is: Day16.hs
build-depends: containers build-depends: containers
executable day17
import: common
hs-source-dirs: src
main-is: Day17.hs
build-depends: libaoc

87
src/Day17.hs Normal file
View File

@@ -0,0 +1,87 @@
module Main where
import qualified AoC as A (extract)
import Data.Bits (Bits (shiftR, xor))
import Data.List (isSuffixOf)
import Text.Parsec (char, digit, many1, newline, parse, sepBy1, string)
import Text.Parsec.String (Parser)
data Instruction = Adv | Bxl | Bst | Jnz | Bxc | Out | Bdv | Cdv deriving (Enum, Show)
type Program = [Int]
type PC = Int
type Registers = (Int, Int, Int)
type Output = [Int]
parseProg :: Parser Program
parseProg = string "Program: " *> ((read <$> many1 digit) `sepBy1` char ',')
parseRegs :: Parser Registers
parseRegs = do
a <- string "Register A: " *> (read <$> many1 digit) <* newline
b <- string "Register B: " *> (read <$> many1 digit) <* newline
c <- string "Register C: " *> (read <$> many1 digit) <* newline
return (a, b, c)
parseInfo :: Parser (Registers, Program)
parseInfo = (,) <$> (parseRegs <* newline) <*> parseProg
steps :: PC -> Registers -> Program -> Output
steps pc regs prog = step pc regs
where
step :: PC -> Registers -> Output
step pc regs@(a, b, c) = case drop pc prog of
[] -> []
ins : op : _ ->
case toEnum ins of
Adv -> step (pc + 2) (a `shiftR` combo, b, c)
Bxl -> step (pc + 2) (a, b `xor` op, c)
Bst -> step (pc + 2) (a, combo `mod` 8, c)
Jnz | a /= 0 -> step op regs
Jnz -> step (pc + 2) regs
Bxc -> step (pc + 2) (a, b `xor` c, c)
Out -> combo `mod` 8 : step (pc + 2) regs
Bdv -> step (pc + 2) (a, a `shiftR` combo, c)
Cdv -> step (pc + 2) (a, b, a `shiftR` combo)
where
combo :: Int
combo = case op of
0 -> 0
1 -> 1
2 -> 2
3 -> 3
4 -> a
5 -> b
6 -> c
_ -> error "invalid operand"
--------------------------------------------------------------
-- Will only work given the following conditions are true --
-- 1. There is only a single loop at the end of program --
-- 2. A is right shifted by 3 every loop --
-- 3. B is the value being printed --
-- 4. Based on the instructions, B is deterministic given A --
--------------------------------------------------------------
part2 :: Program -> Int
part2 prog = go 0
where
go :: Int -> Int
go a
| output == prog = a
| output `isSuffixOf` prog = go $ a * 8
| otherwise = go $ a + 1
where
output = steps 0 (a, 0, 0) prog
main :: IO ()
main =
do
raw <- readFile "./inputs/day17.in"
let (regs, prog) = A.extract $ parse parseInfo "" raw
putStr "Part 1: " >> print (steps 0 regs prog)
putStr "Part 2: " >> print (part2 prog)