From 04c021ff22a5761b32620415b2457267900c1a67 Mon Sep 17 00:00:00 2001 From: Jonathan Chan Date: Wed, 19 Dec 2018 00:02:06 -0800 Subject: [PATCH] Day 19. --- README.md | 2 +- app/Main.hs | 2 +- input/19.txt | 37 ++++++++++++++++++++++++++ input/19_notes.txt | 41 +++++++++++++++++++++++++++++ src/Day17_UArray.hs | 2 +- src/Day19.hs | 63 +++++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 142 insertions(+), 5 deletions(-) create mode 100644 input/19.txt create mode 100644 input/19_notes.txt diff --git a/README.md b/README.md index efcdb4c..9801e72 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Now located in this repository's wiki. | 16 | ~ 1 | | 17 | ~ 15 | | 18 | ~ 6 | -| 19 | | +| 19 | ~ 3 | | 20 | | | 21 | | | 22 | | diff --git a/app/Main.hs b/app/Main.hs index 68ae951..7762ee4 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -30,4 +30,4 @@ import qualified Day24 import qualified Day25 main :: IO () -main = Day18.main +main = Day19.main diff --git a/input/19.txt b/input/19.txt new file mode 100644 index 0000000..783c57c --- /dev/null +++ b/input/19.txt @@ -0,0 +1,37 @@ +#ip 4 +addi 4 16 4 +seti 1 1 1 +seti 1 7 3 +mulr 1 3 2 +eqrr 2 5 2 +addr 2 4 4 +addi 4 1 4 +addr 1 0 0 +addi 3 1 3 +gtrr 3 5 2 +addr 4 2 4 +seti 2 3 4 +addi 1 1 1 +gtrr 1 5 2 +addr 2 4 4 +seti 1 6 4 +mulr 4 4 4 +addi 5 2 5 +mulr 5 5 5 +mulr 4 5 5 +muli 5 11 5 +addi 2 1 2 +mulr 2 4 2 +addi 2 6 2 +addr 5 2 5 +addr 4 0 4 +seti 0 0 4 +setr 4 5 2 +mulr 2 4 2 +addr 4 2 2 +mulr 4 2 2 +muli 2 14 2 +mulr 2 4 2 +addr 5 2 5 +seti 0 5 0 +seti 0 2 4 diff --git a/input/19_notes.txt b/input/19_notes.txt new file mode 100644 index 0000000..5500bbe --- /dev/null +++ b/input/19_notes.txt @@ -0,0 +1,41 @@ +#ip 4 + +0 1 2 3 4 5 6 +a b c d ip f g = 0 + int a = 0; + 0 addi 4 16 4 ip += 16 goto L1 int f = 10551264; + 1 seti 1 1 1 b = 1 L8: b = 1 for (int b = 1; b <= f; b++) { + 2 seti 1 7 3 d = 1 L7: d = 1 for (int d = 1; d <= f; d++) { + 3 mulr 1 3 2 c = b * d L5: c = b * d + 4 eqrr 2 5 2 c = c == f if (b * d == f) if (b * d == f) + 5 addr 2 4 4 ip = ip + c then goto L2 + 6 addi 4 1 4 ip += 1 else goto L3 + 7 addr 1 0 0 a += b L2: a += b a += b; + 8 addi 3 1 3 d += 1 L3: d++ + 9 gtrr 3 5 2 c = d > f if (d > f) +10 addr 4 2 4 ip += c then goto L4 +11 seti 2 3 4 ip = 2 else goto L5 } +12 addi 1 1 1 b += 1 L4: b++ +13 gtrr 1 5 2 c = b > f if (b > f) +14 addr 2 4 4 ip += c then goto L6 +15 seti 1 6 4 ip = 1 else goto L7 } +16 mulr 4 4 4 ip *= ip L6: return return a; +17 addi 5 2 5 f += 2 L1: f = 2 +18 mulr 5 5 5 f *= f f = 2^2 +19 mulr 4 5 5 f *= ip f = 2^2 * 19 +20 muli 5 11 5 f *= 11 f = 2^2 * 19 * 11 = 836 +21 addi 2 1 2 c += 1 c = 1 +22 mulr 2 4 2 c *= ip c = 1 * 22 +23 addi 2 6 2 c += 6 c = 1 * 22 + 6 +24 addr 5 2 5 f += c f = 836 + 1 * 22 + 6 = 864 +25 addr 4 0 4 ip += a if (a == 1) then goto L9 +26 seti 0 0 4 ip = 0 else goto L8 +27 setr 4 5 2 c = ip L9: c = 27 +28 mulr 2 4 2 c *= ip c = 27*28 +29 addr 4 2 2 c += ip c = 27*28 + 29 +30 mulr 4 2 2 c *= ip c = (27*28 + 29) * 30 +31 muli 2 14 2 c *= 14 c = (27*28 + 29) * 30 * 14 +32 mulr 2 4 2 c *= ip c = (27*28 + 29) * 30 * 14 * 32 +33 addr 5 2 5 f += c f = 864 + 10550400 = 10551264 +34 seti 0 5 0 a = 0 a = 0 +35 seti 0 2 4 ip = 0 goto L8 diff --git a/src/Day17_UArray.hs b/src/Day17_UArray.hs index 38789fd..4b604a5 100644 --- a/src/Day17_UArray.hs +++ b/src/Day17_UArray.hs @@ -1,6 +1,6 @@ {-# LANGUAGE TupleSections #-} -module Day17 (main) where +module Day17_UArray (main) where import Prelude hiding (lookup) import Data.Foldable (maximumBy, minimumBy) diff --git a/src/Day19.hs b/src/Day19.hs index 1430c4c..b892292 100644 --- a/src/Day19.hs +++ b/src/Day19.hs @@ -1,6 +1,65 @@ module Day19 (main) where +import Prelude hiding (length) +import Data.List (elemIndex) +import Data.Maybe (catMaybes) +import Data.Bits ((.|.), (.&.)) +import Data.Sequence (Seq, fromList, update, adjust', index, length) + +data Op = Op OpType Int Int Int +data OpType = + Addr | Addi | Mulr | Muli | Banr | Bani | Borr | Bori | + Setr | Seti | Gtir | Gtri | Gtrr | Eqir | Eqri | Eqrr + deriving Enum +type Ops = Seq Op +type Registers = Seq Int + +infixl 9 ! +(!) = index + +execOp :: Op -> Registers -> Registers +execOp (Op Addr rA rB rC) rs = update rC (rs ! rA + rs ! rB) rs +execOp (Op Mulr rA rB rC) rs = update rC (rs ! rA * rs ! rB) rs +execOp (Op Banr rA rB rC) rs = update rC (rs ! rA .&. rs ! rB) rs +execOp (Op Borr rA rB rC) rs = update rC (rs ! rA .|. rs ! rB) rs +execOp (Op Addi rA vB rC) rs = update rC (rs ! rA + vB) rs +execOp (Op Muli rA vB rC) rs = update rC (rs ! rA * vB) rs +execOp (Op Bani rA vB rC) rs = update rC (rs ! rA .&. vB) rs +execOp (Op Bori rA vB rC) rs = update rC (rs ! rA .|. vB) rs +execOp (Op Setr rA _ rC) rs = update rC (rs ! rA) rs +execOp (Op Seti vA _ rC) rs = update rC vA rs +execOp (Op Gtir vA rB rC) rs = update rC (fromEnum $ vA > rs ! rB) rs +execOp (Op Eqir vA rB rC) rs = update rC (fromEnum $ vA == rs ! rB) rs +execOp (Op Gtri rA vB rC) rs = update rC (fromEnum $ rs ! rA > vB) rs +execOp (Op Eqri rA vB rC) rs = update rC (fromEnum $ rs ! rA == vB) rs +execOp (Op Gtrr rA rB rC) rs = update rC (fromEnum $ rs ! rA > rs ! rB) rs +execOp (Op Eqrr rA rB rC) rs = update rC (fromEnum $ rs ! rA == rs ! rB) rs + +opNames = ["addr","addi","mulr","muli","banr","bani","borr","bori","setr","seti","gtir","gtri","gtrr","eqir","eqri","eqrr"] + +parse :: String -> (Int, Ops) +parse input = + let ipBinding:rest = lines input + ip = read $ drop 4 ipBinding + ops = fromList $ map parseOp rest + in (ip, ops) + where + parseOp str = + let opName:a:b:c:[] = words str + Just opType = toEnum <$> elemIndex opName opNames + in Op opType (read a) (read b) (read c) + +-- exec :: the register to which the instruction pointer is bound -> instructions -> initial registers -> final registers +exec :: Int -> Ops -> Registers -> Registers +exec ip ops regs = + let i = regs ! ip + nextRegs = adjust' (+1) ip $ execOp (ops ! i) regs + in if i >= length ops then regs else exec ip ops nextRegs + +part1 :: Int -> Ops -> Int +part1 ip ops = exec ip ops (fromList [0, 0, 0, 0, 0, 0]) ! 0 + main :: IO () main = do - input <- readFile "input/19.txt" - print input \ No newline at end of file + (ip, ops) <- parse <$> readFile "input/19.txt" + print $ part1 ip ops