This repository has been archived by the owner on Jan 2, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
day16.nim
58 lines (50 loc) · 2.05 KB
/
day16.nim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import elfcode, sequtils, strutils, tables
func toInstr(line: string): seq[int] = line.strip.split(" ").map(parseInt)
func toRegisterSample(line: string): seq[int] = line.substr(9, line.len - 2).split(", ").map(parseInt)
proc execute(regs: var seq[int], instr: seq[int], opcodes: array[16, proc(regs: seq[int], a,b: int): int]) =
regs[instr[3]] = opcodes[instr[0]](regs, instr[1], instr[2])
let opsSeq = toSeq(ops.values)
var
before, instr, after: seq[int]
opPossibilities: array[16, array[16, bool]]
opMappings: array[16, proc(regs: seq[int], a,b: int): int]
threeOrMore = 0
step = 0
registers = @[0, 0, 0, 0]
for line in readFile("data/16.txt").splitlines:
if step == 0 and line.len > 6 and line[0..5] == "Before":
before = line.toRegisterSample
step.inc
elif step == 1:
instr = line.toInstr
step.inc
elif step == 2:
after = line.toRegisterSample
var count = 0
for i, op in opsSeq:
var actual: seq[int]
actual.shallowCopy(before)
actual[instr[3]] = op(before, instr[1], instr[2])
if actual == after:
count.inc
else:
opPossibilities[instr[0]][i] = true
if count >= 3:
threeOrMore.inc
step = 0
if step == 0 and line.len > 5 and line[0].isdigit:
# First instruction found after the samples -- figure out which
# opcode belongs to which...
var found: array[16, bool]
while not found.all(proc(v: bool): bool = v):
for opcode, possibilities in opPossibilities:
let matrix = zip(possibilities, found)
if matrix.count((false, false)) == 1:
let index = matrix.find((false, false))
found[index] = true
opMappings[opcode] = opsSeq[index]
step = -1
if step == -1 and line.len > 5:
registers.execute(line.toInstr, opMappings)
echo threeOrMore
echo registers[0]