104 lines
2.4 KiB
Python
104 lines
2.4 KiB
Python
|
from collections import defaultdict
|
||
|
from opcodes import run_op, CONTINUE, HALT, WAIT
|
||
|
|
||
|
class StackIO:
|
||
|
def __init__(self):
|
||
|
self.input_stack = []
|
||
|
self.output_stack = []
|
||
|
|
||
|
def input(self):
|
||
|
return self.input_stack.pop(0)
|
||
|
|
||
|
def output(self, val):
|
||
|
self.output_stack.append(val)
|
||
|
|
||
|
def wait_for_input(self):
|
||
|
return len(self.input_stack) == 0
|
||
|
|
||
|
def pop_out(self):
|
||
|
return self.output_stack.pop(0)
|
||
|
|
||
|
class Memory:
|
||
|
def __init__(self, program=[]):
|
||
|
self.memory = program[:]
|
||
|
|
||
|
def write(self, i, val):
|
||
|
self.memory += [0] * (i - len(self.memory) + 1)
|
||
|
self.memory[i] = val
|
||
|
|
||
|
def read(self, i):
|
||
|
if i >= len(self.memory):
|
||
|
return 0
|
||
|
return self.memory[i]
|
||
|
|
||
|
def copy(self):
|
||
|
return Memory(self.memory[:])
|
||
|
|
||
|
class Computer(object):
|
||
|
def __init__(self, program, IO, i=0, rel_base=0):
|
||
|
self.memory = Memory(program)
|
||
|
self.IO = IO
|
||
|
self.i = i
|
||
|
self.rel_base = rel_base
|
||
|
|
||
|
def run(self):
|
||
|
for exe_state in self:
|
||
|
if exe_state != CONTINUE:
|
||
|
break
|
||
|
return exe_state
|
||
|
|
||
|
def __iter__(self):
|
||
|
return self
|
||
|
|
||
|
def __next__(self):
|
||
|
return self.run_opcode()
|
||
|
|
||
|
def copy(self):
|
||
|
return Computer(self.memory.memory[:], self.IO, self.i, self.rel_base)
|
||
|
|
||
|
class IntComp(Computer):
|
||
|
run_opcode = run_op
|
||
|
|
||
|
def copy(self):
|
||
|
return IntComp(self.memory.memory[:], self.IO, self.i, self.rel_base)
|
||
|
|
||
|
|
||
|
class Display(defaultdict):
|
||
|
def __init__(self, encoding):
|
||
|
super(Display, self).__init__(int)
|
||
|
self.encoding = encoding
|
||
|
|
||
|
def __str__(self):
|
||
|
xs, ys = zip(*self.keys())
|
||
|
X, Y = max(xs)+1, max(ys)+1
|
||
|
return '\n'.join(''.join(self.encoding[self[(x, y)]]
|
||
|
for x in range(X))
|
||
|
for y in range(Y))
|
||
|
|
||
|
|
||
|
|
||
|
class DisplayIO(object):
|
||
|
def __init__(self, display):
|
||
|
self.display = display
|
||
|
self.block = tuple()
|
||
|
|
||
|
def input(self):
|
||
|
return NotImplemented
|
||
|
|
||
|
def wait_for_input(self):
|
||
|
return NotImplemented
|
||
|
|
||
|
def output(self, x):
|
||
|
self.block += (x,)
|
||
|
if len(self.block) == 3:
|
||
|
self.display[self.block[:2]] = self.block[2]
|
||
|
self.block = tuple()
|
||
|
|
||
|
def output(program, input=[], computer=IntComp):
|
||
|
IO = StackIO()
|
||
|
IO.input_stack = input[:]
|
||
|
comp = computer(program, IO)
|
||
|
if comp.run() != HALT:
|
||
|
return False
|
||
|
return IO.output_stack
|