Browse Source

Day 19

master
Chris Smith 5 years ago
parent
commit
855569f7bb
3 changed files with 103 additions and 0 deletions
  1. 2
    0
      answers/19.txt
  2. 37
    0
      data/19.txt
  3. 64
    0
      day19.nim

+ 2
- 0
answers/19.txt View File

@@ -0,0 +1,2 @@
1
+1536
2
+17540352

+ 37
- 0
data/19.txt View File

@@ -0,0 +1,37 @@
1
+#ip 2
2
+addi 2 16 2 #  0: jmp 16
3
+seti 1 0 1  #  1: r[1] = 1
4
+seti 1 3 3  #  2: r[3] = 1
5
+mulr 1 3 5  #  3: r[5] = r[1] * r[3]
6
+eqrr 5 4 5  #  4: r[5] = r[5] == r[4]?
7
+addr 5 2 2  #  5: jmp r[5] (either to 6 or 7)
8
+addi 2 1 2  #  6: jmp 2 (to 9)
9
+addr 1 0 0  #  7: r[0] += r[1]
10
+addi 3 1 3  #  8: r[3]++
11
+gtrr 3 4 5  #  9: r[5] = r[3] > r[4]
12
+addr 2 5 2  # 10: jmp r[5] (either to 11 or 12)
13
+seti 2 6 2  # 11: jmp @2
14
+addi 1 1 1  # 12: r[1]++
15
+gtrr 1 4 5  # 13: r[5] = r[1] > r[4]
16
+addr 5 2 2  # 14: jmp r[5] (either to 15 or 16)
17
+seti 1 1 2  # 15: jmp @1
18
+mulr 2 2 2  # 16: r[2] = 16 * 16 == EXIT
19
+addi 4 2 4  # 17: r[4] += 2
20
+mulr 4 4 4  # 18: r[4] = r[4] * r[4]
21
+mulr 2 4 4  # 19: r[4] = r[2] * r[4] = 19 * r[4]
22
+muli 4 11 4 # 20: r[4] = r[4] * 11
23
+addi 5 6 5  # 21: r[5] += 6
24
+mulr 5 2 5  # 22: r[5] = r[2] * r[5] = 22 * r[5]
25
+addi 5 19 5 # 23: r[5] += 19
26
+addr 4 5 4  # 24: r[4] += r[5]
27
+addr 2 0 2  # 25: jmp r[0]
28
+seti 0 7 2  # 26: jmp @0
29
+setr 2 6 5  # 27: r[5] = 27
30
+mulr 5 2 5  # 28: r[5] = r[5] * r[2] = 27 * 28 = 756
31
+addr 2 5 5  # 29: r[5] = r[5] + r[2] = 756 + 29 = 785
32
+mulr 2 5 5  # 30: r[5] = r[5] * r[2] = 785 * 30 = 23550
33
+muli 5 14 5 # 31: r[5] *= 14 = 329700
34
+mulr 5 2 5  # 32: r[5] = r[5] * r[2] = 10550400
35
+addr 4 5 4  # 33: r[4] = r[4] + r[5] = r[4] + 10550400
36
+seti 0 7 0  # 34: r[0] = 0
37
+seti 0 3 2  # 35: jmp @0

+ 64
- 0
day19.nim View File

@@ -0,0 +1,64 @@
1
+import math, sequtils, strutils, tables
2
+
3
+type instr = tuple[op: string, a,b,c: int]
4
+
5
+let ops = {
6
+    "addi": proc(regs: seq[int], a,b: int): int = regs[a] + b,
7
+    "addr": proc(regs: seq[int], a,b: int): int = regs[a] + regs[b],
8
+
9
+    "muli": proc(regs: seq[int], a,b: int): int = regs[a] * b,
10
+    "mulr": proc(regs: seq[int], a,b: int): int = regs[a] * regs[b],
11
+
12
+    "bani": proc(regs: seq[int], a,b: int): int = regs[a] and b,
13
+    "banr": proc(regs: seq[int], a,b: int): int = regs[a] and regs[b],
14
+
15
+    "bori": proc(regs: seq[int], a,b: int): int = regs[a] or b,
16
+    "borr": proc(regs: seq[int], a,b: int): int = regs[a] or regs[b],
17
+
18
+    "seti": proc(regs: seq[int], a,b: int): int = a,
19
+    "setr": proc(regs: seq[int], a,b: int): int = regs[a],
20
+
21
+    "gtir": proc(regs: seq[int], a,b: int): int = cast[int](a > regs[b]),
22
+    "gtri": proc(regs: seq[int], a,b: int): int = cast[int](regs[a] > b),
23
+    "gtrr": proc(regs: seq[int], a,b: int): int = cast[int](regs[a] > regs[b]),
24
+
25
+    "eqir": proc(regs: seq[int], a,b: int): int = cast[int](a == regs[b]),
26
+    "eqri": proc(regs: seq[int], a,b: int): int = cast[int](regs[a] == b),
27
+    "eqrr": proc(regs: seq[int], a,b: int): int = cast[int](regs[a] == regs[b]),
28
+}.toTable
29
+
30
+var
31
+    instructions: seq[instr]
32
+    ip: int
33
+
34
+for line in readFile("data/19.txt").strip.splitlines:
35
+    var parts = line.split(' ')
36
+    if parts[0] == "#ip":
37
+        ip = parts[1].parseInt
38
+    else:
39
+        instructions.add((parts[0], parts[1].parseInt, parts[2].parseInt, parts[3].parseInt))
40
+
41
+proc findTarget(part2: bool): int =
42
+    # The instructions calculate the sum of all factors of a target number. The
43
+    # target is initialised first, and then execution jumps back to near the
44
+    # start of the program to perform the calculation. To find the target
45
+    # number, we evaluate until a backwards jump and then just take the largest
46
+    # register. (Yuck.)
47
+    var registers = @[if part2: 1 else: 0, 0, 0, 0, 0, 0]
48
+    while true:
49
+        let
50
+            i = registers[ip]
51
+            instr = instructions[i]
52
+        registers[instr.c] = ops[instr.op](registers, instr.a, instr.b)
53
+        registers[ip].inc
54
+        if registers[ip] < i:
55
+            return registers.max
56
+
57
+proc factors(n: int): seq[int] =
58
+    for x in 1 .. int(sqrt(float(n))):
59
+        if n mod x == 0:
60
+            result.add(x)
61
+            result.add(n div x)
62
+   
63
+echo findTarget(false).factors.sum
64
+echo findTarget(true).factors.sum