enum begin NOP = 0, LDA, STA, ADD, SUB, BRZ, JMP, STP end local ops = {NOP = NOP, LDA = LDA, STA = STA, ADD = ADD, SUB = SUB, BRZ = BRZ, JMP = JMP, STP = STP} local function load(prog) local mem = table.create(31, 1) for i = 0, 31 do mem[i] = 0 end local lines = prog:rstrip():split("\n") for i = 1, #lines do local line = lines[i]:strip() local split = line:split(" ") local instr = split[1] local addr = 0 if #split == 2 then addr = tonumber(split[2]) end if ops[instr] then mem[i - 1] = ops[instr] * 32 + addr else local v = tonumber(instr) if v then mem[i - 1] = v end end end return mem end local function output(acc) print(acc) end local function interp(prog) local acc = 0 local pc = 0 local mem = load(prog) while true do local instr = mem[pc] >> 5 local addr = mem[pc] % 32 pc += 1 switch instr do case LDA: acc = mem[addr] break case STA: mem[addr] = acc break case ADD: acc += mem[addr] if acc > 255 then acc -= 256 end break case SUB: acc -= mem[addr] if acc < 0 then ac += 256 end break case BRZ: if acc == 0 then pc = addr end break case JMP: pc = addr break end if instr == STP or pc > 31 then break end end output(acc) end local progs = { [[ LDA 3 ADD 4 STP 2 2 ]], [[ LDA 12 ADD 10 STA 12 LDA 11 SUB 13 STA 11 BRZ 8 JMP 0 LDA 12 STP 8 7 0 1 ]], [[ LDA 14 STA 15 ADD 13 STA 14 LDA 15 STA 13 LDA 16 SUB 17 BRZ 11 STA 16 JMP 0 LDA 14 STP 1 1 0 8 1 ]], [[ LDA 13 ADD 15 STA 5 ADD 16 STA 7 NOP STA 14 NOP BRZ 11 STA 15 JMP 0 LDA 14 STP LDA 0 0 28 1 6 0 2 26 5 20 3 30 1 22 4 24 ]], [[ 0 0 STP NOP LDA 3 SUB 29 BRZ 18 LDA 3 STA 29 BRZ 14 LDA 1 ADD 31 STA 1 JMP 2 LDA 0 ADD 31 STA 0 JMP 2 LDA 3 STA 29 LDA 0 ADD 30 ADD 3 STA 0 LDA 1 ADD 30 ADD 3 STA 1 JMP 2 0 1 3 ]] } for progs as prog do interp(prog) end