···11+# True = read, False = write
22+INSTRUCTIONS = {
33+ 1: ('ADD', (True, True, False)),
44+ 2: ('MUL', (True, True, False)),
55+ 3: ('INP', (False, None, None)),
66+ 4: ('OUT', (True, None, None)),
77+ 5: ('JZ ', (True, True, None)),
88+ 6: ('JNZ', (True, True, None)),
99+ 7: ('LT ', (True, True, False)),
1010+ 8: ('EQ ', (True, True, False)),
1111+ 9: ('REL', (True, None, None)),
1212+ 99: ('HLT', (None, None, None)),
1313+}
1414+1515+1616+def parse_mode(tape, mode_op, a, b, c):
1717+ op = mode_op % 100
1818+ mode_a = (mode_op // 100) % 10
1919+ mode_b = (mode_op // 1000) % 10
2020+ mode_c = (mode_op // 10000) % 10
2121+2222+ return op, mode_a, mode_b, mode_c
2323+2424+2525+def emulate(tape, pid, GLOBAL_INPUTS, pc=0):
2626+ tape = tape[:]
2727+ relative_base = 0
2828+2929+ def resolve_modes(op, params, modes):
3030+ res = [a, b, c]
3131+3232+ for i, (is_read, p, m) in enumerate(zip(INSTRUCTIONS[op][1], params, modes)):
3333+ if is_read is None:
3434+ continue
3535+3636+ if is_read:
3737+ if m == 0:
3838+ res[i] = tape[p]
3939+ elif m == 1:
4040+ res[i] = p
4141+ elif m == 2:
4242+ res[i] = tape[relative_base + p]
4343+ else:
4444+ if m == 0:
4545+ res[i] = p
4646+ elif m == 2:
4747+ res[i] = relative_base + p
4848+4949+ return res
5050+5151+ while pc < len(tape):
5252+ mode_op, a, b, c = tape[pc:pc+4]
5353+ op, mode_a, mode_b, mode_c = parse_mode(tape, mode_op, a, b, c)
5454+ a, b, c = resolve_modes(op, (a, b, c), (mode_a, mode_b, mode_c))
5555+5656+ # ADD a b c
5757+ if op == 1:
5858+ tape[c] = a + b
5959+ pc += 4
6060+6161+ # MUL a b c
6262+ elif op == 2:
6363+ tape[c] = a * b
6464+ pc += 4
6565+6666+ # INP a
6767+ elif op == 3:
6868+ tape[a] = GLOBAL_INPUTS[pid]
6969+ pc += 2
7070+7171+ # OUT b
7272+ elif op == 4:
7373+ yield a
7474+ pc += 2
7575+7676+ # JZ a b
7777+ elif op == 5:
7878+ if a != 0:
7979+ pc = b
8080+ else:
8181+ pc += 3
8282+8383+ # JNZ a b
8484+ elif op == 6:
8585+ if a == 0:
8686+ pc = b
8787+ else:
8888+ pc += 3
8989+9090+ # LT a b c
9191+ elif op == 7:
9292+ tape[c] = 1 if a < b else 0
9393+ pc += 4
9494+9595+ # EQ a b c
9696+ elif op == 8:
9797+ tape[c] = 1 if a == b else 0
9898+ pc += 4
9999+100100+ elif op == 9:
101101+ relative_base += a
102102+ pc += 2
103103+104104+ # HALT
105105+ elif op == 99:
106106+ raise StopIteration()