Browse Source

Day 16

master
Chris Smith 5 years ago
parent
commit
8fe21edd1b
3 changed files with 3946 additions and 0 deletions
  1. 2
    0
      answers/16.txt
  2. 3863
    0
      data/16.txt
  3. 81
    0
      day16.nim

+ 2
- 0
answers/16.txt View File

@@ -0,0 +1,2 @@
1
+509
2
+496

+ 3863
- 0
data/16.txt
File diff suppressed because it is too large
View File


+ 81
- 0
day16.nim View File

@@ -0,0 +1,81 @@
1
+import sequtils, strutils
2
+
3
+let ops = [
4
+    proc(regs: seq[int], a,b: int): int = regs[a] + b,
5
+    proc(regs: seq[int], a,b: int): int = regs[a] + regs[b],
6
+
7
+    proc(regs: seq[int], a,b: int): int = regs[a] * b,
8
+    proc(regs: seq[int], a,b: int): int = regs[a] * regs[b],
9
+
10
+    proc(regs: seq[int], a,b: int): int = regs[a] and b,
11
+    proc(regs: seq[int], a,b: int): int = regs[a] and regs[b],
12
+
13
+    proc(regs: seq[int], a,b: int): int = regs[a] or b,
14
+    proc(regs: seq[int], a,b: int): int = regs[a] or regs[b],
15
+
16
+    proc(regs: seq[int], a,b: int): int = a,
17
+    proc(regs: seq[int], a,b: int): int = regs[a],
18
+
19
+    proc(regs: seq[int], a,b: int): int = cast[int](a > regs[b]),
20
+    proc(regs: seq[int], a,b: int): int = cast[int](regs[a] > b),
21
+    proc(regs: seq[int], a,b: int): int = cast[int](regs[a] > regs[b]),
22
+
23
+    proc(regs: seq[int], a,b: int): int = cast[int](a == regs[b]),
24
+    proc(regs: seq[int], a,b: int): int = cast[int](regs[a] == b),
25
+    proc(regs: seq[int], a,b: int): int = cast[int](regs[a] == regs[b]),
26
+]
27
+
28
+func toInstr(line: string): seq[int] = line.strip.split(" ").map(parseInt)
29
+func toRegisterSample(line: string): seq[int] = line.substr(9, line.len - 2).split(", ").map(parseInt)
30
+
31
+proc execute(regs: var seq[int], instr: seq[int], opcodes: array[16, proc(regs: seq[int], a,b: int): int]) =
32
+    regs[instr[3]] = opcodes[instr[0]](regs, instr[1], instr[2])
33
+
34
+var
35
+    before, instr, after: seq[int]
36
+    opPossibilities: array[16, array[16, bool]]
37
+    opMappings: array[16, proc(regs: seq[int], a,b: int): int]
38
+    threeOrMore = 0
39
+    step = 0
40
+    registers = @[0, 0, 0, 0]
41
+
42
+for line in readFile("data/16.txt").splitlines:
43
+    if step == 0 and line.len > 6 and line[0..5] == "Before":
44
+        before = line.toRegisterSample
45
+        step.inc
46
+    elif step == 1:
47
+        instr = line.toInstr
48
+        step.inc
49
+    elif step == 2:
50
+        after = line.toRegisterSample
51
+        var count = 0
52
+        for i, op in ops:
53
+            var actual: seq[int]
54
+            actual.shallowCopy(before)
55
+            actual[instr[3]] = op(before, instr[1], instr[2])
56
+            if actual == after:
57
+                count.inc
58
+            else:
59
+                opPossibilities[instr[0]][i] = true
60
+        if count >= 3:
61
+            threeOrMore.inc
62
+        step = 0
63
+    
64
+    if step == 0 and line.len > 5 and line[0].isdigit:
65
+        # First instruction found after the samples -- figure out which
66
+        # opcode belongs to which...
67
+        var found: array[16, bool]
68
+        while not found.all(proc(v: bool): bool = v):
69
+            for opcode, possibilities in opPossibilities:
70
+                let matrix = zip(possibilities, found)
71
+                if matrix.count((false, false)) == 1:
72
+                    let index = matrix.find((false, false))
73
+                    found[index] = true
74
+                    opMappings[opcode] = ops[index]
75
+        step = -1
76
+    
77
+    if step == -1:
78
+        registers.execute(line.toInstr, opMappings)
79
+
80
+echo threeOrMore
81
+echo registers[0]