Modules for intcode computer. Old code, commiting before changes
parent
554ea25596
commit
31d860b227
|
@ -0,0 +1,103 @@
|
|||
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
|
|
@ -0,0 +1,98 @@
|
|||
from operator import add, mul, eq, lt
|
||||
import enum
|
||||
|
||||
|
||||
@enum.unique
|
||||
class State(enum.Enum):
|
||||
"""Execution state class."""
|
||||
CONTINUE = 0
|
||||
HALT = 1
|
||||
WAIT = 2
|
||||
|
||||
|
||||
class Opcode:
|
||||
def __init__(self, func, parnum):
|
||||
self.parnum = parnum
|
||||
self.run = func
|
||||
|
||||
|
||||
def operation(operator):
|
||||
"""Make opcode from operator."""
|
||||
def opcode(state, p1, p2, p3):
|
||||
state.memory.write(p3, operator(state.memory.read(p1), state.memory.read(p2)))
|
||||
state.i += 4
|
||||
return State.CONTINUE
|
||||
return Opcode(opcode, 3)
|
||||
|
||||
def jump(flag):
|
||||
def opcode(state, p1, p2):
|
||||
state.i = state.memory.read(p2) if (state.memory.read(p1) > 0)==flag else state.i+3
|
||||
return State.CONTINUE
|
||||
return Opcode(opcode, 2)
|
||||
|
||||
def adjust_base(state, p1):
|
||||
state.rel_base += state.memory.read(p1)
|
||||
state.i += 2
|
||||
return State.CONTINUE
|
||||
|
||||
def input(state, p1):
|
||||
if state.IO.wait_for_input():
|
||||
return State.WAIT
|
||||
state.memory.write(p1, state.IO.input())
|
||||
state.i += 2
|
||||
return State.CONTINUE
|
||||
|
||||
def output(state, p1):
|
||||
state.IO.output(state.memory.read(p1))
|
||||
state.i += 2
|
||||
return State.CONTINUE
|
||||
|
||||
|
||||
op_add = operation(add)
|
||||
|
||||
op_mul = operation(mul)
|
||||
|
||||
op_lt = operation(lt)
|
||||
|
||||
op_eq = operation(eq)
|
||||
|
||||
op_jump_if_true = jump(True)
|
||||
|
||||
op_jump_if_false = jump(False)
|
||||
|
||||
op_adjust_relative_base = Opcode(adjust_base, 1)
|
||||
|
||||
op_input = Opcode(input, 1)
|
||||
|
||||
op_output = Opcode(output, 1)
|
||||
|
||||
op_halt = Opcode(lambda x: State.HALT, 0)
|
||||
|
||||
opcodes = {1 : op_add,
|
||||
2 : op_mul,
|
||||
3 : op_input,
|
||||
4 : op_output,
|
||||
5 : op_jump_if_true,
|
||||
6 : op_jump_if_false,
|
||||
7 : op_lt,
|
||||
8 : op_eq,
|
||||
9 : op_adjust_relative_base,
|
||||
99 : op_halt}
|
||||
|
||||
def parse_op(op):
|
||||
op = str(op)
|
||||
par_modes, op = op[:-2][::-1], int(op[-2:])
|
||||
par_modes = par_modes + '0'*(opcodes[op].parnum - len(par_modes))
|
||||
return op, map(int, par_modes)
|
||||
|
||||
def run_op(state):
|
||||
op, par_modes = parse_op(state.memory.read(state.i))
|
||||
pars = []
|
||||
for pn, mode in enumerate(par_modes, start=1):
|
||||
p = state.i + pn
|
||||
if mode == 0:
|
||||
p = state.memory.read(p)
|
||||
elif mode == 2:
|
||||
p = state.rel_base + state.memory.read(p)
|
||||
pars.append(p)
|
||||
return opcodes[op].run(state, *pars)
|
Loading…
Reference in New Issue