90 lines
2.8 KiB
Python
90 lines
2.8 KiB
Python
# SPDX-License-Identifier: MIT
|
|
# Copyright (c) 2019 Akumatic
|
|
|
|
class InvalidOpcode(Exception):
|
|
pass
|
|
|
|
class IndexError(Exception):
|
|
pass
|
|
|
|
class Data:
|
|
def __init__(self, vals: list):
|
|
self._data = {i:vals[i] for i in range(len(vals))}
|
|
|
|
def __getitem__(self, idx):
|
|
if idx < 0:
|
|
raise IndexError("Negative Index")
|
|
if idx in self._data:
|
|
return self._data[idx]
|
|
self._data[idx] = 0
|
|
return 0
|
|
|
|
def __setitem__(self, idx, val):
|
|
if idx < 0:
|
|
raise IndexError("Negative Index")
|
|
self._data[idx] = val
|
|
|
|
def toList(self):
|
|
return list(self._data.values())
|
|
|
|
def parseCode(i: int) -> tuple:
|
|
return (i % 100, i // 100 % 10, i // 1000 % 10, i // 10000 % 10)
|
|
|
|
def getOutput(vals: list, input=0, base=0, full_out: bool = False,
|
|
getVals: bool = False, output: bool=False) -> int:
|
|
vals = Data(vals)
|
|
i = 0
|
|
out = []
|
|
while True:
|
|
opcode = parseCode(vals[i])
|
|
|
|
# 0 Parameter
|
|
if opcode[0] == 99: # Termination
|
|
if output:
|
|
return out
|
|
if getVals:
|
|
return vals.toList()
|
|
if full_out:
|
|
return vals, out
|
|
return vals[0]
|
|
|
|
# 1 Parameter
|
|
elif opcode[0] in (3,4,9):
|
|
a = vals[i+1] if not opcode[1] else i+1 if opcode[1] == 1 else base+vals[i+1]
|
|
if opcode[0] == 3: # Input
|
|
vals[a] = input
|
|
elif opcode[0] == 4: # Output
|
|
vals[0] = vals[a]
|
|
out.append(vals[0])
|
|
elif opcode[0] == 9: # Adjust Base
|
|
base += vals[a]
|
|
i += 2
|
|
|
|
# 2 Parameter
|
|
elif opcode[0] in (5,6):
|
|
a = vals[i+1] if not opcode[1] else i+1 if opcode[1] == 1 else base+vals[i+1]
|
|
b = vals[i+2] if not opcode[2] else i+2 if opcode[2] == 1 else base+vals[i+2]
|
|
if opcode[0] == 5 and vals[a] != 0: # Jump-if-true
|
|
i = vals[b]
|
|
elif opcode[0] == 6 and vals[a] == 0: # Jump-if-false
|
|
i = vals[b]
|
|
else:
|
|
i += 3
|
|
|
|
# 3 Parameter
|
|
elif opcode[0] in (1,2,7,8):
|
|
a = vals[i+1] if not opcode[1] else i+1 if opcode[1] == 1 else base+vals[i+1]
|
|
b = vals[i+2] if not opcode[2] else i+2 if opcode[2] == 1 else base+vals[i+2]
|
|
c = vals[i+3] if not opcode[3] else i+3 if opcode[3] == 1 else base+vals[i+3]
|
|
if opcode[0] == 1: # Addition
|
|
vals[c] = vals[a] + vals[b]
|
|
elif opcode[0] == 2: # Multiplication
|
|
vals[c] = vals[a] * vals[b]
|
|
elif opcode[0] == 7: # Less Than
|
|
vals[c] = int(vals[a] < vals[b])
|
|
elif opcode[0] == 8: # Equals
|
|
vals[c] = int(vals[a] == vals[b])
|
|
i += 4
|
|
|
|
else:
|
|
raise InvalidOpcode() |