Intcode/Interpreters
Jump to navigation
Jump to search
This page is for interpreters of Intcode that don't have their own website or external repository.
Python
arities = {
1: 4, #Take x, y, z write x+y to pos z
2: 4, #" " x*y to pos z
3: 2, #Write input to pos x
4: 2, #Print item at pos x
5: 3, #If pos x == 0: jump to pos y
6: 3, #If pos x != 0: jump to pos y
7: 4, #Write x < y to pos z
8: 4, #Write x == y to pos z
9: 2, #Change relative position
99:0 #End of execution
} #Default arity is 1
functions = {
1: lambda stack, lhs, rhs, location, modes: stack.set_item(location,
stack.get_data(lhs, modes.pop()) + stack.get_data(rhs, modes.pop())),
2: lambda stack, lhs, rhs, location, modes: stack.set_item(location,
stack.get_data(lhs, modes.pop()) * stack.get_data(rhs, modes.pop())),
3: lambda stack, location, modes: stack.set_item(location, int(input())),
4: lambda stack, location, modes: print(stack.get_data(location,
modes.pop())),
}
def extract_command(integer):
command = str(integer)
if len(command) <= 2:
return (integer, Stack())
else:
op = command[-2:]
modes = command[:-2]
return (int(op), Stack([int(char) for char in modes]))
class Stack:
def __init__(self, iterable=[]):
if iterable:
self.stack = iterable
else:
self.stack = []
self.rel_base = 0
self.ip = 0
def __len__(self):
return len(self.stack)
def __setitem__(self, index, value):
if type(index) == slice:
idx = index.stop + 1
else:
idx = index + 1
if idx > len(self.stack):
for _ in range(idx - len(self.stack)):
self.stack.append(0)
self.stack[index] = value
def __getitem__(self, index):
if type(index) == slice:
idx = index.stop + 1
else:
idx = index + 1
if idx >= len(self.stack):
for _ in range(idx - len(self.stack)):
self.stack.append(0)
return self.stack[index]
def __delitem__(self, what):
del self.stack[what]
def get_data(self, pos, mode):
if mode == 0: #Position mode:
return self.__getitem__(pos)
elif mode == 1: #Immediate
return pos
elif mode == 2:
x = self.rel_base + pos
return self.__getitem__(x)
def opcode_9(self, value):
self.rel_base += value
def pop(self):
if len(self.stack):
return self.stack.pop()
else:
return 0
def set_item(self, location, value):
self.__setitem__(location, value)
def main(program):
prog = Stack([int(tkn) for tkn in program.split(",")])
ip = 0
while ip < len(prog):
opcode, modes = extract_command(prog[ip])
arity = arities[opcode]
if opcode in [1, 2]:
command = functions[opcode]
lhs = prog[ip + 1]
rhs = prog[ip + 2]
location = prog[ip + 3]
if len(modes) == 3 and modes[0] == 2:
location += prog.rel_base
command(prog, lhs, rhs, location, modes)
ip += arity
elif opcode == 3:
command = functions[opcode]
if len(modes) and modes[0] == 2:
command(prog, prog[ip + 1] + prog.rel_base, modes)
else:
command(prog, *prog[ip+1 : ip + arity], modes)
ip += arity
elif opcode == 4:
command = functions[opcode]
command(prog, *prog[ip+1 : ip + arity], modes)
ip += arity
elif opcode == 5:
condition = prog.get_data(prog[ip + 1], modes.pop())
if condition:
jump_position = prog.get_data(prog[ip + 2], modes.pop())
ip = jump_position
else:
ip += arity
elif opcode == 6:
condition = prog.get_data(prog[ip + 1], modes.pop())
if not condition:
jump_position = prog.get_data(prog[ip + 2], modes.pop())
ip = jump_position
else:
ip += arity
elif opcode == 7:
lhs = prog.get_data(prog[ip + 1], modes.pop())
rhs = prog.get_data(prog[ip + 2], modes.pop())
location = prog[ip + 3]
if modes.pop() == 2:
location += prog.rel_base
if lhs < rhs:
prog[location] = 1
else:
prog[location] = 0
ip += arity
elif opcode == 8:
lhs = prog.get_data(prog[ip + 1], modes.pop())
rhs = prog.get_data(prog[ip + 2], modes.pop())
location = prog[ip + 3]
if modes.pop() == 2:
location += prog.rel_base
if lhs == rhs:
prog[location] = 1
else:
prog[location] = 0
ip += arity
elif opcode == 9:
value = prog.get_data(prog[ip + 1], modes.pop())
prog.opcode_9(value)
ip += arity
elif opcode == 99:
break
return "Final value: ", prog.stack
if __name__ == "__main__":
program = input()
print(main(program))