2023-11-23 01:31:57 +01:00
|
|
|
from collections import defaultdict
|
|
|
|
|
|
|
|
|
|
|
2023-11-23 17:08:13 +01:00
|
|
|
"""
|
|
|
|
|
intcode computer, AoC 2019
|
2023-11-23 01:31:57 +01:00
|
|
|
|
2023-11-23 17:08:13 +01:00
|
|
|
Changelog
|
|
|
|
|
=========
|
2023-11-23 01:31:57 +01:00
|
|
|
|
2023-11-23 17:08:13 +01:00
|
|
|
0.3.0
|
|
|
|
|
-----
|
2023-11-23 01:31:57 +01:00
|
|
|
|
2023-11-23 17:08:13 +01:00
|
|
|
Minor release (day 7 part 1-2).
|
2023-11-23 01:31:57 +01:00
|
|
|
|
2023-11-23 17:08:13 +01:00
|
|
|
BREAKING CHANGE: execute() now returns 4 values.
|
|
|
|
|
- now: exit code, state at halt, instruction position at halt, and captured stdout.
|
|
|
|
|
- before: final state, and captured stdout
|
2023-11-23 01:31:57 +01:00
|
|
|
|
2023-11-23 17:08:13 +01:00
|
|
|
Changes:
|
2023-11-23 01:31:57 +01:00
|
|
|
|
2023-11-23 17:08:13 +01:00
|
|
|
- Add support for a sequence of stdins
|
|
|
|
|
- Add interactive param to ask for manual (interactive) input on input opcode
|
|
|
|
|
- Add verbose param to show more output in interactive input mode
|
|
|
|
|
- Will now halt with code 3 (input) when input is required, stdin is empty and interactive input mode is not enabled
|
2023-11-23 01:31:57 +01:00
|
|
|
|
2023-11-23 17:08:13 +01:00
|
|
|
0.2.1
|
|
|
|
|
-----
|
2023-11-23 01:31:57 +01:00
|
|
|
|
2023-11-23 17:08:13 +01:00
|
|
|
Patch release (day 5 part 2).
|
2023-11-23 01:31:57 +01:00
|
|
|
|
2023-11-23 17:08:13 +01:00
|
|
|
- Add operation 5: set instruction pointer to value at parameter 2 position, based on value at parameter 1 position
|
|
|
|
|
- Add operation 6: set instruction pointer to value at parameter 2 position, based on value at parameter 1 position
|
|
|
|
|
- Add operation 7: compares values in parameter 1 position and parameter 2 position, stores at parameter 3 position
|
|
|
|
|
- Add operation 8: compares values in parameter 1 position and parameter 2 position, stores at parameter 3 position
|
2023-11-23 01:31:57 +01:00
|
|
|
|
2023-11-23 17:08:13 +01:00
|
|
|
0.2.0
|
|
|
|
|
-----
|
2023-11-23 01:31:57 +01:00
|
|
|
|
2023-11-23 17:08:13 +01:00
|
|
|
Minor release (day 5 part 1).
|
2023-11-23 01:31:57 +01:00
|
|
|
|
2023-11-23 17:08:13 +01:00
|
|
|
- Support immediate parameter mode
|
|
|
|
|
- Add stdin argument
|
|
|
|
|
- Make arguments optional: noun, verb
|
|
|
|
|
- Capture and return stdout
|
|
|
|
|
- Add operation 3: store stdin to parameter 1 position
|
|
|
|
|
- Add operation 4: output value at parameter 1 position to stdout
|
2023-11-23 01:31:57 +01:00
|
|
|
|
2023-11-23 17:08:13 +01:00
|
|
|
0.1.1
|
|
|
|
|
-----
|
|
|
|
|
|
|
|
|
|
Patch release (day 2 part 2).
|
|
|
|
|
|
|
|
|
|
- Remove initial modification 1=12, 2=2
|
|
|
|
|
- Add noun argument, stored at pos 1 (default value: 12)
|
|
|
|
|
- Add verb argument, stored at pos 2 (default value: 2)
|
|
|
|
|
|
|
|
|
|
0.1.0
|
|
|
|
|
-----
|
|
|
|
|
|
|
|
|
|
Initial version (day 2 part 1).
|
|
|
|
|
|
|
|
|
|
- Support positional parameter mode
|
|
|
|
|
- Add operation 1: adds parameter 1 to parameter 2, store to parameter 3 position
|
|
|
|
|
- Add operation 2: multiply parameter 1 with parameter 2, store to parameter 3 position
|
|
|
|
|
"""
|
|
|
|
|
v = "0.2.3"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def parse(data):
|
|
|
|
|
return list(map(int, data.split(",")))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def execute(
|
|
|
|
|
program,
|
|
|
|
|
noun=None,
|
|
|
|
|
verb=None,
|
|
|
|
|
stdin=[],
|
|
|
|
|
debug=False,
|
|
|
|
|
interactive=False,
|
|
|
|
|
verbose=False,
|
|
|
|
|
n=0,
|
|
|
|
|
):
|
|
|
|
|
if verbose:
|
|
|
|
|
title = f"intcode computer, version {v}"
|
|
|
|
|
print("".join("=" for _ in title))
|
|
|
|
|
print(title)
|
|
|
|
|
print("".join("=" for _ in title))
|
2023-11-23 01:31:57 +01:00
|
|
|
state = dict(zip(range(len(program)), program))
|
|
|
|
|
if noun:
|
|
|
|
|
state[1] = noun
|
|
|
|
|
if verb:
|
|
|
|
|
state[2] = verb
|
|
|
|
|
c = 0
|
|
|
|
|
stdout = []
|
2023-11-23 17:08:13 +01:00
|
|
|
if not isinstance(stdin, list):
|
|
|
|
|
stdin = [stdin]
|
2023-11-23 01:31:57 +01:00
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
instruction = state[n]
|
|
|
|
|
opcode = instruction % 100
|
|
|
|
|
modes = str(instruction // 100 % 100).zfill(2)
|
|
|
|
|
if opcode == 1:
|
|
|
|
|
a = state[n + 1]
|
|
|
|
|
b = state[n + 2]
|
|
|
|
|
p = state[n + 3]
|
|
|
|
|
x = a if modes[1] == "1" else state[a]
|
|
|
|
|
y = b if modes[0] == "1" else state[b]
|
|
|
|
|
state[p] = x + y
|
|
|
|
|
n += 4
|
|
|
|
|
if debug:
|
|
|
|
|
print(f"{n}:{opcode} | {x} + {y} to {p}")
|
|
|
|
|
if opcode == 2:
|
|
|
|
|
a = state[n + 1]
|
|
|
|
|
b = state[n + 2]
|
|
|
|
|
p = state[n + 3]
|
|
|
|
|
x = a if modes[1] == "1" else state[a]
|
|
|
|
|
y = b if modes[0] == "1" else state[b]
|
|
|
|
|
state[p] = x * y
|
|
|
|
|
n += 4
|
|
|
|
|
if debug:
|
|
|
|
|
print(f"{n}:{opcode} | {x} * {y} to {p}")
|
|
|
|
|
if opcode == 3:
|
|
|
|
|
p = state[n + 1]
|
2023-11-23 17:08:13 +01:00
|
|
|
if stdin:
|
|
|
|
|
state[p] = stdin.pop(0)
|
|
|
|
|
else:
|
|
|
|
|
if interactive:
|
|
|
|
|
state[p] = int(input("> "))
|
|
|
|
|
else:
|
|
|
|
|
return 3, state, n, stdout
|
2023-11-23 01:31:57 +01:00
|
|
|
n += 2
|
|
|
|
|
if debug:
|
|
|
|
|
print(f"{n}:{opcode} | {i} to {p}")
|
|
|
|
|
if opcode == 4:
|
|
|
|
|
a = state[n + 1]
|
|
|
|
|
x = a if modes[1] == "1" else state[a]
|
|
|
|
|
n += 2
|
|
|
|
|
stdout.append(x)
|
2023-11-23 17:08:13 +01:00
|
|
|
if verbose:
|
|
|
|
|
print(x)
|
2023-11-23 01:31:57 +01:00
|
|
|
if debug:
|
|
|
|
|
print(f"{n}:{opcode} | {stdout}")
|
|
|
|
|
if opcode == 5:
|
|
|
|
|
a = state[n + 1]
|
|
|
|
|
b = state[n + 2]
|
|
|
|
|
x = a if modes[1] == "1" else state[a]
|
|
|
|
|
y = b if modes[0] == "1" else state[b]
|
|
|
|
|
if x != 0:
|
|
|
|
|
n = y
|
|
|
|
|
else:
|
|
|
|
|
n += 3
|
|
|
|
|
if debug:
|
|
|
|
|
print(f"{n}:{opcode} | {n}")
|
|
|
|
|
if opcode == 6:
|
|
|
|
|
a = state[n + 1]
|
|
|
|
|
b = state[n + 2]
|
|
|
|
|
x = a if modes[1] == "1" else state[a]
|
|
|
|
|
y = b if modes[0] == "1" else state[b]
|
|
|
|
|
if x == 0:
|
|
|
|
|
n = y
|
|
|
|
|
else:
|
|
|
|
|
n += 3
|
|
|
|
|
if debug:
|
|
|
|
|
print(f"{n}:{opcode} | {n}")
|
|
|
|
|
if opcode == 7:
|
|
|
|
|
a = state[n + 1]
|
|
|
|
|
b = state[n + 2]
|
|
|
|
|
p = state[n + 3]
|
|
|
|
|
x = a if modes[1] == "1" else state[a]
|
|
|
|
|
y = b if modes[0] == "1" else state[b]
|
|
|
|
|
state[p] = int(x < y)
|
|
|
|
|
n += 4
|
|
|
|
|
if debug:
|
|
|
|
|
print(f"{n}:{opcode} | {x}")
|
|
|
|
|
if opcode == 8:
|
|
|
|
|
a = state[n + 1]
|
|
|
|
|
b = state[n + 2]
|
|
|
|
|
p = state[n + 3]
|
|
|
|
|
x = a if modes[1] == "1" else state[a]
|
|
|
|
|
y = b if modes[0] == "1" else state[b]
|
|
|
|
|
state[p] = int(x == y)
|
|
|
|
|
n += 4
|
|
|
|
|
if debug:
|
|
|
|
|
print(f"{n}:{opcode} | {x}")
|
|
|
|
|
if opcode == 99:
|
|
|
|
|
break
|
|
|
|
|
c += 1
|
|
|
|
|
if debug and c % 1000 == 0:
|
|
|
|
|
print(f"{c} instructions done, current pos: {n}")
|
|
|
|
|
# if c == 3:
|
|
|
|
|
# break
|
2023-11-23 17:08:13 +01:00
|
|
|
if verbose:
|
|
|
|
|
title = f"intcode computer received SIGTERM"
|
|
|
|
|
return 99, state, n, stdout
|