95 lines
3.3 KiB
Python
Raw Normal View History

2019-12-09 20:34:51 +01:00
""" https://adventofcode.com/2019/day/9 """
class InvalidOpcode(Exception):
pass
class mylist(list):
def __getitem__(self, item):
try:
return super(mylist,self).__getitem__(item)
except IndexError as e:
if item < 0: raise IndexError()
super(mylist,self).extend([0]*(item + 1 - super(mylist,self).__len__()))
return super(mylist,self).__getitem__(item)
def __setitem__(self, idx, val):
try:
return super(mylist,self).__setitem__(idx,val)
except IndexError as e:
if idx < 0: raise IndexError()
super(mylist,self).extend([0]*(idx + 1 - super(mylist,self).__len__()))
return super(mylist,self).__setitem__(idx,val)
def readFile():
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
return [int(num) for num in f.readline().split(",")]
def getOutput(vals : list, input=0, base=0):
vals = mylist(vals)
i = 0
while 1:
opcode = (vals[i] % 100,
vals[i] // 100 % 10,
vals[i] // 1000 % 10,
vals[i] // 10000 % 10)
# 0 Parameter
if opcode[0] in [99]: # Termination
return vals
# 1 Parameter
elif opcode[0] in [3,4,9]:
a = vals[i+1] if not opcode[1] else i+1 if opcode[1] == 1 else base+vals[i+1]
if opcode[0] == 3: # Input
vals[a] = input
elif opcode[0] == 4: # Output
vals[0] = vals[a]
elif opcode[0] == 9: # Adjust Base
base += vals[a]
i += 2
# 2 Parameter
elif opcode[0] in [5,6]:
a = vals[i+1] if not opcode[1] else i+1 if opcode[1] == 1 else base+vals[i+1]
b = vals[i+2] if not opcode[2] else i+2 if opcode[2] == 1 else base+vals[i+2]
if opcode[0] == 5 and vals[a] != 0: # Jump-if-true
i = vals[b]
elif opcode[0] == 6 and vals[a] == 0: # Jump-if-false
i = vals[b]
else:
i += 3
# 3 Parameter
elif opcode[0] in [1,2,7,8]:
a = vals[i+1] if not opcode[1] else i+1 if opcode[1] == 1 else base+vals[i+1]
b = vals[i+2] if not opcode[2] else i+2 if opcode[2] == 1 else base+vals[i+2]
c = vals[i+3] if not opcode[3] else i+3 if opcode[3] == 1 else base+vals[i+3]
if opcode[0] == 1: # Addition
vals[c] = vals[a] + vals[b]
elif opcode[0] == 2: # Multiplication
vals[c] = vals[a] * vals[b]
elif opcode[0] == 7: # Less Than
vals[c] = int(vals[a] < vals[b])
elif opcode[0] == 8: # Equals
vals[c] = int(vals[a] == vals[b])
i += 4
else:
raise InvalidOpcode()
def part1(vals : list):
return getOutput(vals.copy(), input=1)[0]
def part2(vals : list):
return getOutput(vals.copy(), input=2)[0]
def test():
assert getOutput([104,1125899906842624,99])[0] == 1125899906842624
assert len(getOutput([109,19,204,-34,99], base=2000)) == 1986
assert len(str(getOutput([1102,34915192,34915192,7,4,7,99,0])[0])) == 16
if __name__ == "__main__":
test()
vals = readFile()
print(f"Part 1: {part1(vals)}")
print(f"Part 2: {part2(vals)}")