Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # -*- coding: utf-8 -*-
- from pprint import pprint
- # cpu state
- ram = {}
- ip = 0
- tick = 0
- # debugging/qol functions
- debug = 0
- singlestep = 0
- # IO
- def input_():
- return int(input("Enter input: "))
- def output_(n):
- print("OUT: " + str(n))
- # instructions, param_modes is a string not an int,
- # 0 = positional,
- # 1 = immediate
- def op1(param_modes):
- """add"""
- store(load(ip + 3),
- getparam(1, param_modes) + getparam(2, param_modes))
- def op2(param_modes):
- """mul"""
- store(load(ip + 3),
- getparam(1, param_modes) * getparam(2, param_modes))
- def op3(param_modes):
- """save input to a cell in ram"""
- store(load(ip + 1), input_())
- def op4(param_modes):
- """output the contents of a cell in ram"""
- output_(getparam(1, param_modes))
- def op5(param_modes):
- """jump if true"""
- global ip
- if getparam(1, param_modes) != 0:
- dbgprint('jumping to ' + str(getparam(2, param_modes)))
- ip = getparam(2, param_modes)
- # compensate for the IP getting incremented after each
- # instruction in clocktick
- ip -= 3
- def op6(param_modes):
- """jump if false"""
- global ip
- if getparam(1, param_modes) == 0:
- dbgprint('jumping to ' + str(getparam(2, param_modes)))
- ip = getparam(2, param_modes)
- # compensate for the IP getting incremented after each
- # instruction in clocktick
- ip -= 3
- def op7(param_modes):
- """less than"""
- if getparam(1, param_modes) < getparam(2, param_modes):
- store(load(ip + 3), 1)
- else:
- store(load(ip + 3), 0)
- def op8(param_modes):
- """equals"""
- if getparam(1, param_modes) == getparam(2, param_modes):
- store(load(ip + 3), 1)
- else:
- store(load(ip + 3), 0)
- def op99(param_modes):
- """halt"""
- print("halting...\n")
- #print("dumping ram:\n")
- # dumpram()
- raise Exception()
- def getparam(ipoffset, param_modes):
- # ipoffset = parameter number, i.e. param 1 = ip+1, etc
- mode = 0
- try:
- mode = int(param_modes[-ipoffset])
- except IndexError:
- pass # missing modes default to 0
- if mode == 0:
- return load(load(ip+ipoffset))
- if mode == 1:
- return load(ip+ipoffset)
- else:
- print("invalid parameter mode: " + str(mode))
- raise Exception()
- # maps opcode number (two digits) to a tuple with the actual function to run,
- # plus the length to jump ahead after executing
- opcodes = {
- 1: (op1, 4),
- 2: (op2, 4),
- 3: (op3, 2),
- 4: (op4, 2),
- 5: (op5, 3),
- 6: (op6, 3),
- 7: (op7, 4),
- 8: (op8, 4),
- 99: (op99, 4)
- }
- # read/write from ram - all accesses to ram must go through load() or store()
- def store(address, value):
- ram[address] = value
- def load(address):
- try:
- return ram[address]
- except KeyError:
- # if we read an address in ram that hasnt been written to
- return 0
- # actual execution happens here
- def opexec(opcode):
- # opcode here is the full opcode with all digits
- param_modes = str(opcode)[:-2]
- try:
- # look up the opcode and run its corresponding function
- opcodes[int(str(opcode)[-2:])][0](param_modes)
- except KeyError:
- #print("dumping ram:\n")
- # dumpram()
- raise RuntimeError(f"unknown opcode: {opcode}")
- def clocktick():
- global ip
- global tick
- opcode = load(ip)
- dbgprint("tick: " + str(tick) + " op: " + str(opcode))
- if singlestep:
- while input():
- # while singlestepping, you can type any input to get a
- # dump of ram. this is nice when debugging
- dumpram()
- opexec(opcode)
- ip += opcodes[int(str(opcode)[-2:])][1]
- tick += 1
- def loadprogram(program):
- # program is intcode string
- c = 0
- for i in [x for x in map(int, program.split(','))]:
- store(c, i)
- c += 1
- def dbgprint(s):
- if debug:
- print(s)
- def dumpram():
- pprint(ram)
- print("ip: " + str(ip))
- def resetstate():
- global ram
- global ip
- global tick
- ram = {}
- ip = 0
- tick = 0
- def runprogram(program):
- """convenience function just to run a program"""
- resetstate()
- loadprogram(program)
- print("program loaded:\n")
- dumpram()
- input("press enter to proceed.")
- print("starting execution\n")
- while (1):
- try:
- clocktick()
- except Exception as e:
- print("execution halted\n")
- dbgprint(type(e))
- break
- def main():
- with open("input.txt") as f:
- p = f.read()
- runprogram(p)
- if __name__ == "__main__":
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement