Advertisement
Guest User

Untitled

a guest
Dec 5th, 2019
156
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.78 KB | None | 0 0
  1. # -*- coding: utf-8 -*-
  2. from pprint import pprint
  3.  
  4. # cpu state
  5. ram = {}
  6. ip = 0
  7. tick = 0
  8.  
  9. # debugging/qol functions
  10. debug = 0
  11. singlestep = 0
  12.  
  13.  
  14. # IO
  15. def input_():
  16.     return int(input("Enter input: "))
  17.  
  18.  
  19. def output_(n):
  20.     print("OUT: " + str(n))
  21.  
  22.  
  23. # instructions, param_modes is a string not an int,
  24. # 0 = positional,
  25. # 1 = immediate
  26. def op1(param_modes):
  27.     """add"""
  28.     store(load(ip + 3),
  29.           getparam(1, param_modes) + getparam(2, param_modes))
  30.  
  31.  
  32. def op2(param_modes):
  33.     """mul"""
  34.     store(load(ip + 3),
  35.           getparam(1, param_modes) * getparam(2, param_modes))
  36.  
  37.  
  38. def op3(param_modes):
  39.     """save input to a cell in ram"""
  40.     store(load(ip + 1), input_())
  41.  
  42.  
  43. def op4(param_modes):
  44.     """output the contents of a cell in ram"""
  45.     output_(getparam(1, param_modes))
  46.  
  47.  
  48. def op5(param_modes):
  49.     """jump if true"""
  50.     global ip
  51.     if getparam(1, param_modes) != 0:
  52.         dbgprint('jumping to ' + str(getparam(2, param_modes)))
  53.         ip = getparam(2, param_modes)
  54.         # compensate for the IP getting incremented after each
  55.         # instruction in clocktick
  56.         ip -= 3
  57.  
  58.  
  59. def op6(param_modes):
  60.     """jump if false"""
  61.     global ip
  62.     if getparam(1, param_modes) == 0:
  63.         dbgprint('jumping to ' + str(getparam(2, param_modes)))
  64.         ip = getparam(2, param_modes)
  65.         # compensate for the IP getting incremented after each
  66.         # instruction in clocktick
  67.         ip -= 3
  68.  
  69.  
  70. def op7(param_modes):
  71.     """less than"""
  72.     if getparam(1, param_modes) < getparam(2, param_modes):
  73.         store(load(ip + 3), 1)
  74.     else:
  75.         store(load(ip + 3), 0)
  76.  
  77.  
  78. def op8(param_modes):
  79.     """equals"""
  80.     if getparam(1, param_modes) == getparam(2, param_modes):
  81.         store(load(ip + 3), 1)
  82.     else:
  83.         store(load(ip + 3), 0)
  84.  
  85.  
  86. def op99(param_modes):
  87.     """halt"""
  88.     print("halting...\n")
  89.     #print("dumping ram:\n")
  90.     # dumpram()
  91.     raise Exception()
  92.  
  93.  
  94. def getparam(ipoffset, param_modes):
  95.     # ipoffset = parameter number, i.e. param 1 = ip+1, etc
  96.  
  97.     mode = 0
  98.     try:
  99.         mode = int(param_modes[-ipoffset])
  100.     except IndexError:
  101.         pass  # missing modes default to 0
  102.  
  103.     if mode == 0:
  104.         return load(load(ip+ipoffset))
  105.     if mode == 1:
  106.         return load(ip+ipoffset)
  107.     else:
  108.         print("invalid parameter mode: " + str(mode))
  109.         raise Exception()
  110.  
  111.  
  112. # maps opcode number (two digits) to a tuple with the actual function to run,
  113. # plus the length to jump ahead after executing
  114. opcodes = {
  115.         1: (op1, 4),
  116.         2: (op2, 4),
  117.         3: (op3, 2),
  118.         4: (op4, 2),
  119.         5: (op5, 3),
  120.         6: (op6, 3),
  121.         7: (op7, 4),
  122.         8: (op8, 4),
  123.         99: (op99, 4)
  124. }
  125.  
  126.  
  127. # read/write from ram - all accesses to ram must go through load() or store()
  128. def store(address, value):
  129.     ram[address] = value
  130.  
  131.  
  132. def load(address):
  133.     try:
  134.         return ram[address]
  135.     except KeyError:
  136.         # if we read an address in ram that hasnt been written to
  137.         return 0
  138.  
  139.  
  140. # actual execution happens here
  141. def opexec(opcode):
  142.     # opcode here is the full opcode with all digits
  143.     param_modes = str(opcode)[:-2]
  144.  
  145.     try:
  146.         # look up the opcode and run its corresponding function
  147.         opcodes[int(str(opcode)[-2:])][0](param_modes)
  148.     except KeyError:
  149.         #print("dumping ram:\n")
  150.         # dumpram()
  151.         raise RuntimeError(f"unknown opcode: {opcode}")
  152.  
  153.  
  154. def clocktick():
  155.     global ip
  156.     global tick
  157.  
  158.     opcode = load(ip)
  159.     dbgprint("tick: " + str(tick) + " op: " + str(opcode))
  160.  
  161.     if singlestep:
  162.         while input():
  163.             # while singlestepping, you can type any input to get a
  164.             # dump of ram. this is nice when debugging
  165.             dumpram()
  166.  
  167.     opexec(opcode)
  168.     ip += opcodes[int(str(opcode)[-2:])][1]
  169.     tick += 1
  170.  
  171.  
  172. def loadprogram(program):
  173.     # program is intcode string
  174.     c = 0
  175.     for i in [x for x in map(int, program.split(','))]:
  176.         store(c, i)
  177.         c += 1
  178.  
  179.  
  180. def dbgprint(s):
  181.     if debug:
  182.         print(s)
  183.  
  184.  
  185. def dumpram():
  186.     pprint(ram)
  187.     print("ip: " + str(ip))
  188.  
  189.  
  190. def resetstate():
  191.     global ram
  192.     global ip
  193.     global tick
  194.  
  195.     ram = {}
  196.     ip = 0
  197.     tick = 0
  198.  
  199.  
  200. def runprogram(program):
  201.     """convenience function just to run a program"""
  202.     resetstate()
  203.     loadprogram(program)
  204.  
  205.     print("program loaded:\n")
  206.     dumpram()
  207.     input("press enter to proceed.")
  208.  
  209.     print("starting execution\n")
  210.  
  211.     while (1):
  212.         try:
  213.             clocktick()
  214.         except Exception as e:
  215.             print("execution halted\n")
  216.             dbgprint(type(e))
  217.             break
  218.  
  219.  
  220. def main():
  221.     with open("input.txt") as f:
  222.         p = f.read()
  223.     runprogram(p)
  224.  
  225.  
  226. if __name__ == "__main__":
  227.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement