2019 Day 13 Part 2; intcode as class; intcode_test to assure functionality; changed old code to adapt intcode computer as object
This commit is contained in:
parent
592513f6b7
commit
0d748eae52
@ -5,26 +5,28 @@
|
|||||||
|
|
||||||
import sys, os
|
import sys, os
|
||||||
sys.path.insert(1, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
sys.path.insert(1, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
import intcode
|
import intcode, intcode_test
|
||||||
|
|
||||||
def readFile() -> list:
|
def readFile() -> list:
|
||||||
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
||||||
return [int(num) for num in f.readline().split(",")]
|
return [int(num) for num in f.readline().split(",")]
|
||||||
|
|
||||||
def part1(vals: list) -> int:
|
def part1(pc: intcode.Computer) -> int:
|
||||||
memory = vals.copy()
|
pc.data[1], pc.data[2] = 12, 2
|
||||||
memory[1], memory[2] = 12, 2
|
pc.run()
|
||||||
return intcode.getOutput(memory)
|
return pc.data[0]
|
||||||
|
|
||||||
def part2(vals: list) -> int:
|
def part2(pc: intcode.Computer) -> int:
|
||||||
for noun in range(100):
|
for noun in range(100):
|
||||||
for verb in range(100):
|
for verb in range(100):
|
||||||
memory = vals.copy()
|
pc.reset()
|
||||||
memory[1], memory[2] = noun, verb
|
pc.data[1], pc.data[2] = noun, verb
|
||||||
if intcode.getOutput(memory) == 19690720:
|
pc.run()
|
||||||
|
if pc.data[0] == 19690720:
|
||||||
return 100 * noun + verb
|
return 100 * noun + verb
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
vals = readFile()
|
intcode_test.test_02()
|
||||||
print(f"Part 1: {part1(vals)}")
|
pc = intcode.Computer(readFile())
|
||||||
print(f"Part 2: {part2(vals)}")
|
print(f"Part 1: {part1(pc)}")
|
||||||
|
print(f"Part 2: {part2(pc)}")
|
@ -5,44 +5,24 @@
|
|||||||
|
|
||||||
import sys, os
|
import sys, os
|
||||||
sys.path.insert(1, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
sys.path.insert(1, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
import intcode
|
import intcode, intcode_test
|
||||||
|
|
||||||
def readFile() -> list:
|
def readFile() -> list:
|
||||||
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
||||||
return [int(num) for num in f.readline().split(",")]
|
return [int(num) for num in f.readline().split(",")]
|
||||||
|
|
||||||
def part1(vals: list) -> int:
|
def part1(pc: intcode.Computer) -> int:
|
||||||
return intcode.getOutput(vals.copy(), input=1)
|
pc.reset(input=1)
|
||||||
|
pc.run()
|
||||||
|
return pc.data[0]
|
||||||
|
|
||||||
def part2(vals: list) -> int:
|
def part2(pc: intcode.Computer) -> int:
|
||||||
return intcode.getOutput(vals.copy(), input=5)
|
pc.reset(input=5)
|
||||||
|
pc.run()
|
||||||
def test():
|
return pc.data[0]
|
||||||
assert intcode.parseCode(1001) == (1, 0, 1, 0)
|
|
||||||
assert intcode.getOutput([1,0,0,0,99]) == 2
|
|
||||||
assert intcode.getOutput([1,1,1,4,99,5,6,0,99]) == 30
|
|
||||||
assert intcode.getOutput([3,0,4,0,99], input=42) == 42
|
|
||||||
assert intcode.getOutput([1101,100,-1,4,0], getVals=True) == [1101,100,-1,4,99]
|
|
||||||
assert intcode.getOutput([3,9,8,9,10,9,4,9,99,-1,8], input=0) == 0
|
|
||||||
assert intcode.getOutput([3,9,8,9,10,9,4,9,99,-1,8], input=8) == 1
|
|
||||||
assert intcode.getOutput([3,9,7,9,10,9,4,9,99,-1,8], input=0) == 1
|
|
||||||
assert intcode.getOutput([3,9,7,9,10,9,4,9,99,-1,8], input=8) == 0
|
|
||||||
assert intcode.getOutput([3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9], input=0) == 0
|
|
||||||
assert intcode.getOutput([3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9], input=1) == 1
|
|
||||||
assert intcode.getOutput([3,3,1105,-1,9,1101,0,0,12,4,12,99,1], input=0) == 0
|
|
||||||
assert intcode.getOutput([3,3,1105,-1,9,1101,0,0,12,4,12,99,1], input=1) == 1
|
|
||||||
assert intcode.getOutput([3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,
|
|
||||||
1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,999,1105,1,46,
|
|
||||||
1101,1000,1,20,4,20,1105,1,46,98,99], input=0) == 999
|
|
||||||
assert intcode.getOutput([3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,
|
|
||||||
1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,999,1105,1,46,
|
|
||||||
1101,1000,1,20,4,20,1105,1,46,98,99], input=8) == 1000
|
|
||||||
assert intcode.getOutput([3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,
|
|
||||||
1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,999,1105,1,46,
|
|
||||||
1101,1000,1,20,4,20,1105,1,46,98,99], input=9) == 1001
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
test()
|
intcode_test.test_05()
|
||||||
vals = readFile()
|
pc = intcode.Computer(readFile())
|
||||||
print(f"Part 1: {part1(vals)}")
|
print(f"Part 1: {part1(pc)}")
|
||||||
print(f"Part 2: {part2(vals)}")
|
print(f"Part 2: {part2(pc)}")
|
@ -5,24 +5,24 @@
|
|||||||
|
|
||||||
import sys, os
|
import sys, os
|
||||||
sys.path.insert(1, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
sys.path.insert(1, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
import intcode
|
import intcode, intcode_test
|
||||||
|
|
||||||
def readFile() -> list:
|
def readFile() -> list:
|
||||||
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
||||||
return [int(num) for num in f.readline().split(",")]
|
return [int(num) for num in f.readline().split(",")]
|
||||||
|
|
||||||
def part1(vals: list) -> int:
|
def part1(pc: intcode.Computer) -> int:
|
||||||
return intcode.getOutput(vals.copy(), input=1)
|
pc.reset(input=1)
|
||||||
|
pc.run()
|
||||||
|
return pc.data[0]
|
||||||
|
|
||||||
def part2(vals: list) -> int:
|
def part2(pc: intcode.Computer) -> int:
|
||||||
return intcode.getOutput(vals.copy(), input=2)
|
pc.reset(input=2)
|
||||||
|
pc.run()
|
||||||
def test():
|
return pc.data[0]
|
||||||
assert intcode.getOutput([104,1125899906842624,99]) == 1125899906842624
|
|
||||||
assert len(str(intcode.getOutput([1102,34915192,34915192,7,4,7,99,0]))) == 16
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
test()
|
intcode_test.test_09()
|
||||||
vals = readFile()
|
pc = intcode.Computer(readFile())
|
||||||
print(f"Part 1: {part1(vals)}")
|
print(f"Part 1: {part1(pc)}")
|
||||||
print(f"Part 2: {part2(vals)}")
|
print(f"Part 2: {part2(pc)}")
|
164
2019/13/code.py
164
2019/13/code.py
@ -1,110 +1,84 @@
|
|||||||
""" https://adventofcode.com/2019/day/13 """
|
# SPDX-License-Identifier: MIT
|
||||||
|
# Copyright (c) 2019 Akumatic
|
||||||
|
#
|
||||||
|
# https://adventofcode.com/2019/day/13
|
||||||
|
|
||||||
class InvalidOpcode(Exception):
|
import sys, os
|
||||||
pass
|
sys.path.insert(1, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
import intcode
|
||||||
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():
|
def readFile():
|
||||||
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
||||||
return [int(num) for num in f.readline().split(",")]
|
return [int(num) for num in f.readline().split(",")]
|
||||||
|
|
||||||
def getOutput(vals : list, input=0, base=0):
|
def getEntities(vals: list):
|
||||||
vals = mylist(vals)
|
assert len(vals) % 3 == 0
|
||||||
i = 0
|
entities = {"empty": [], "wall": [], "block": [],
|
||||||
out = []
|
"paddle": tuple(), "ball": tuple(), "score": 0}
|
||||||
while 1:
|
keys = tuple(entities.keys())
|
||||||
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, out
|
|
||||||
|
|
||||||
# 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]
|
|
||||||
out.append(vals[0])
|
|
||||||
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
|
|
||||||
|
|
||||||
|
for i in range(0, len(vals), 3):
|
||||||
|
# updated score
|
||||||
|
if (vals[i] == -1 and vals[i+1] == 0):
|
||||||
|
entities["score"] = vals[i+2]
|
||||||
|
continue
|
||||||
|
# updated ball, paddle and other positions
|
||||||
|
pos = (vals[i], vals[i+1])
|
||||||
|
if vals[i+2] < 3:
|
||||||
|
entities[keys[vals[i+2]]].append(pos)
|
||||||
else:
|
else:
|
||||||
raise InvalidOpcode()
|
entities[keys[vals[i+2]]] = pos
|
||||||
|
|
||||||
def getEntities():
|
|
||||||
output = getOutput(vals.copy())[1]
|
|
||||||
output.reverse()
|
|
||||||
assert len(output) % 3 == 0
|
|
||||||
entities = [set() for _ in range(5)]
|
|
||||||
while output:
|
|
||||||
pos = (output.pop(), output.pop())
|
|
||||||
tile = output.pop()
|
|
||||||
entities[tile].add(pos)
|
|
||||||
return entities
|
return entities
|
||||||
|
|
||||||
def part1(entities):
|
def part1(pc: intcode.Computer) -> int:
|
||||||
print([len(x) for x in entities])
|
pc.run()
|
||||||
print(entities[3], entities[4])
|
entities = getEntities(pc.output)
|
||||||
return len(entities[2])
|
return len(entities["block"])
|
||||||
|
|
||||||
class Ball:
|
def part2(pc: intcode.Computer) -> int:
|
||||||
def __init__(self, x, y):
|
pc.reset(wait_for_input=True)
|
||||||
self.x, self.y = 0,0
|
pc.data[0] = 2
|
||||||
self.dx, self.dy = 0,0
|
|
||||||
|
|
||||||
def part2(entities):
|
# initial setup
|
||||||
pass
|
pc.run()
|
||||||
|
idx = pc.output.index(-1)
|
||||||
|
while pc.output[idx + 1] != 0:
|
||||||
|
idx = pc.output.index(-1, idx + 1)
|
||||||
|
entities = getEntities(pc.output[:idx])
|
||||||
|
pc.output = pc.output[idx:]
|
||||||
|
|
||||||
|
# loop
|
||||||
|
while not pc.stop:
|
||||||
|
pc.run()
|
||||||
|
changes = getEntities(pc.output)
|
||||||
|
if changes["score"]:
|
||||||
|
entities["score"] = changes["score"]
|
||||||
|
|
||||||
|
if changes["ball"]:
|
||||||
|
changes["empty"].remove(entities["ball"])
|
||||||
|
entities["ball"] = changes["ball"]
|
||||||
|
|
||||||
|
if changes["paddle"]:
|
||||||
|
changes["empty"].remove(entities["paddle"])
|
||||||
|
entities["paddle"] = changes["paddle"]
|
||||||
|
|
||||||
|
for e in changes["empty"]:
|
||||||
|
entities["block"].remove(e)
|
||||||
|
|
||||||
|
pc.output.clear()
|
||||||
|
pc.input = entities["ball"][0] - entities["paddle"][0]
|
||||||
|
|
||||||
|
return entities["score"]
|
||||||
|
|
||||||
|
def test():
|
||||||
|
test_input = [1, 2, 3, 6, 5, 4]
|
||||||
|
test_output = getEntities(test_input)
|
||||||
|
assert test_output["empty"] == test_output["wall"] == test_output["block"] == []
|
||||||
|
assert test_output["paddle"] == (1, 2) and test_output["ball"] == (6, 5)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
vals = readFile()
|
test()
|
||||||
entities = getEntities()
|
pc = intcode.Computer(readFile())
|
||||||
print(f"Part 1: {part1(entities)}")
|
print(f"Part 1: {part1(pc)}")
|
||||||
#print(f"Part 2: {part2(entities)}")
|
print(f"Part 2: {part2(pc)}")
|
@ -1 +1,2 @@
|
|||||||
Part 1: 200
|
Part 1: 200
|
||||||
|
Part 2: 9803
|
@ -18,7 +18,7 @@ Collect stars by solving puzzles. Two puzzles will be made available on each day
|
|||||||
| 07 | :white_check_mark: | :white_check_mark: || 08 | :white_check_mark: | :white_check_mark: |
|
| 07 | :white_check_mark: | :white_check_mark: || 08 | :white_check_mark: | :white_check_mark: |
|
||||||
| 09 | :white_check_mark: | :white_check_mark: || 10 | :white_check_mark: | :white_check_mark: |
|
| 09 | :white_check_mark: | :white_check_mark: || 10 | :white_check_mark: | :white_check_mark: |
|
||||||
| 11 | | || 12 | :white_check_mark: | :white_check_mark: |
|
| 11 | | || 12 | :white_check_mark: | :white_check_mark: |
|
||||||
| 13 | | || 14 | | |
|
| 13 | :white_check_mark: | :white_check_mark: || 14 | | |
|
||||||
| 15 | | || 16 | | |
|
| 15 | | || 16 | | |
|
||||||
| 17 | | || 18 | | |
|
| 17 | | || 18 | | |
|
||||||
| 19 | | || 20 | | |
|
| 19 | | || 20 | | |
|
||||||
|
203
2019/intcode.py
203
2019/intcode.py
@ -1,5 +1,5 @@
|
|||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
# Copyright (c) 2019 Akumatic
|
# Copyright (c) 2020 Akumatic
|
||||||
|
|
||||||
class InvalidOpcode(Exception):
|
class InvalidOpcode(Exception):
|
||||||
pass
|
pass
|
||||||
@ -27,64 +27,153 @@ class Data:
|
|||||||
def toList(self):
|
def toList(self):
|
||||||
return list(self._data.values())
|
return list(self._data.values())
|
||||||
|
|
||||||
def parseCode(i: int) -> tuple:
|
def maxIdx(self):
|
||||||
return (i % 100, i // 100 % 10, i // 1000 % 10, i // 10000 % 10)
|
return max(self._data.keys())
|
||||||
|
|
||||||
def getOutput(vals: list, input=0, base=0, full_out: bool = False,
|
class Computer:
|
||||||
getVals: bool = False, output: bool=False) -> int:
|
def __init__(self,
|
||||||
vals = Data(vals)
|
vals: list,
|
||||||
i = 0
|
base: int = 0,
|
||||||
out = []
|
input: int = 0,
|
||||||
while True:
|
wait_for_input: bool = False
|
||||||
opcode = parseCode(vals[i])
|
):
|
||||||
|
self._val_backup = vals.copy()
|
||||||
# 0 Parameter
|
self.reset(base=base, input=input, wait_for_input=wait_for_input)
|
||||||
if opcode[0] == 99: # Termination
|
|
||||||
if output:
|
|
||||||
return out
|
|
||||||
if getVals:
|
|
||||||
return vals.toList()
|
|
||||||
if full_out:
|
|
||||||
return vals, out
|
|
||||||
return vals[0]
|
|
||||||
|
|
||||||
# 1 Parameter
|
def reset(self, vals = None, base = 0, input = 0, wait_for_input = False):
|
||||||
elif opcode[0] in (3,4,9):
|
if vals is not None:
|
||||||
a = vals[i+1] if not opcode[1] else i+1 if opcode[1] == 1 else base+vals[i+1]
|
self._val_backup = vals
|
||||||
if opcode[0] == 3: # Input
|
self.data: Data = Data(self._val_backup)
|
||||||
vals[a] = input
|
self.base: int = base
|
||||||
elif opcode[0] == 4: # Output
|
self.input: int = None if wait_for_input else input
|
||||||
vals[0] = vals[a]
|
self.pointer: int = 0
|
||||||
out.append(vals[0])
|
self.base: int = base
|
||||||
elif opcode[0] == 9: # Adjust Base
|
self.input: int = input
|
||||||
base += vals[a]
|
self.output: list = list()
|
||||||
i += 2
|
self.opcode: tuple = None
|
||||||
|
self.stop = False
|
||||||
|
self.wait = False
|
||||||
|
|
||||||
|
# # # # # # # # # # #
|
||||||
|
# opcode functions #
|
||||||
|
# # # # # # # # # # #
|
||||||
|
|
||||||
# 2 Parameter
|
# opcode 99
|
||||||
elif opcode[0] in (5,6):
|
def __terminate(self):
|
||||||
a = vals[i+1] if not opcode[1] else i+1 if opcode[1] == 1 else base+vals[i+1]
|
self.stop = True
|
||||||
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
|
|
||||||
|
|
||||||
|
# opcode 1
|
||||||
|
def __add(self, a: int, b: int, c: int):
|
||||||
|
self.data[c] = self.data[a] + self.data[b]
|
||||||
|
self.pointer += 4
|
||||||
|
|
||||||
|
# opcode 2
|
||||||
|
def __multiply(self, a: int, b: int, c: int): # 2
|
||||||
|
self.data[c] = self.data[a] * self.data[b]
|
||||||
|
self.pointer += 4
|
||||||
|
|
||||||
|
# opcode 3
|
||||||
|
def __input(self, a: int): # 3
|
||||||
|
self.data[a] = self.input
|
||||||
|
self.pointer += 2
|
||||||
|
|
||||||
|
# opcode 4
|
||||||
|
def __output(self, a: int): # 4
|
||||||
|
self.data[0] = self.data[a]
|
||||||
|
self.output.append(self.data[0])
|
||||||
|
self.pointer += 2
|
||||||
|
|
||||||
|
# opcode 5
|
||||||
|
def __jump_if_true(self, a: int, b: int): # 5
|
||||||
|
if self.data[a]:
|
||||||
|
self.pointer = self.data[b]
|
||||||
else:
|
else:
|
||||||
raise InvalidOpcode()
|
self.pointer += 3
|
||||||
|
|
||||||
|
# opcode 6
|
||||||
|
def __jump_if_false(self, a: int, b: int): # 6
|
||||||
|
if not self.data[a]:
|
||||||
|
self.pointer = self.data[b]
|
||||||
|
else:
|
||||||
|
self.pointer += 3
|
||||||
|
|
||||||
|
# opcode 7
|
||||||
|
def __less_than(self, a: int, b: int, c: int): # 7
|
||||||
|
self.data[c] = int(self.data[a] < self.data[b])
|
||||||
|
self.pointer += 4
|
||||||
|
|
||||||
|
# opcode 8
|
||||||
|
def __equals(self, a: int, b: int, c: int): # 8
|
||||||
|
self.data[c] = int(self.data[a] == self.data[b])
|
||||||
|
self.pointer += 4
|
||||||
|
|
||||||
|
# opcode 9
|
||||||
|
def __adjust_base(self, a: int): # 9
|
||||||
|
self.base += self.data[a]
|
||||||
|
self.pointer += 2
|
||||||
|
|
||||||
|
# # # # # # # # # # # # #
|
||||||
|
# operational functions #
|
||||||
|
# # # # # # # # # # # # #
|
||||||
|
|
||||||
|
def __setOpcode(self):
|
||||||
|
self.opcode = (
|
||||||
|
self.data[self.pointer] % 100,
|
||||||
|
self.data[self.pointer] // 100 % 10,
|
||||||
|
self.data[self.pointer] // 1000 % 10,
|
||||||
|
self.data[self.pointer] // 10000 % 10
|
||||||
|
)
|
||||||
|
|
||||||
|
def __getParameter(self, n: int):
|
||||||
|
params = list()
|
||||||
|
for i in range(1, n + 1):
|
||||||
|
params.append(
|
||||||
|
self.data[self.pointer + i] if self.opcode[i] == 0 else \
|
||||||
|
self.pointer + i if self.opcode[i] == 1 else \
|
||||||
|
self.data[self.pointer + i] + self.base
|
||||||
|
)
|
||||||
|
return params
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
while not self.stop:
|
||||||
|
self.__setOpcode()
|
||||||
|
|
||||||
|
if self.opcode[0] == 99:
|
||||||
|
self.__terminate()
|
||||||
|
|
||||||
|
elif self.opcode[0] == 1: # add
|
||||||
|
self.__add(*self.__getParameter(3))
|
||||||
|
|
||||||
|
elif self.opcode[0] == 2: # multiply
|
||||||
|
self.__multiply(*self.__getParameter(3))
|
||||||
|
|
||||||
|
elif self.opcode[0] == 3: # input
|
||||||
|
if self.input is not None:
|
||||||
|
if self.wait:
|
||||||
|
self.wait = False
|
||||||
|
self.__input(*self.__getParameter(1))
|
||||||
|
self.input = None
|
||||||
|
else:
|
||||||
|
self.wait = True
|
||||||
|
return
|
||||||
|
|
||||||
|
elif self.opcode[0] == 4: # output
|
||||||
|
self.__output(*self.__getParameter(1))
|
||||||
|
|
||||||
|
elif self.opcode[0] == 5: # jump if true
|
||||||
|
self.__jump_if_true(*self.__getParameter(2))
|
||||||
|
|
||||||
|
elif self.opcode[0] == 6: # jump if false
|
||||||
|
self.__jump_if_false(*self.__getParameter(2))
|
||||||
|
|
||||||
|
elif self.opcode[0] == 7: # less than
|
||||||
|
self.__less_than(*self.__getParameter(3))
|
||||||
|
|
||||||
|
elif self.opcode[0] == 8: # equals
|
||||||
|
self.__equals(*self.__getParameter(3))
|
||||||
|
|
||||||
|
elif self.opcode[0] == 9: # adjust base
|
||||||
|
self.__adjust_base(*self.__getParameter(1))
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise InvalidOpcode
|
59
2019/intcode_test.py
Normal file
59
2019/intcode_test.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import intcode
|
||||||
|
|
||||||
|
def test_02():
|
||||||
|
pc = intcode.Computer([1,0,0,0,99])
|
||||||
|
pc.run()
|
||||||
|
assert pc.data.toList() == [2,0,0,0,99]
|
||||||
|
pc.reset(vals=[2,3,0,3,99]), pc.run()
|
||||||
|
assert pc.data.toList() == [2,3,0,6,99]
|
||||||
|
pc.reset(vals=[2,4,4,5,99,0]), pc.run()
|
||||||
|
assert pc.data.toList() == [2,4,4,5,99,9801]
|
||||||
|
pc.reset(vals=[1,1,1,4,99,5,6,0,99]), pc.run()
|
||||||
|
assert pc.data.toList() == [30,1,1,4,2,5,6,0,99]
|
||||||
|
|
||||||
|
def test_05():
|
||||||
|
pc = intcode.Computer([1,0,0,0,99])
|
||||||
|
pc.run()
|
||||||
|
assert pc.data[0] == 2
|
||||||
|
pc.reset(vals=[1,1,1,4,99,5,6,0,99]), pc.run()
|
||||||
|
assert pc.data[0] == 30
|
||||||
|
pc.reset(vals=[3,0,4,0,99], input=42), pc.run()
|
||||||
|
assert pc.data[0] == 42
|
||||||
|
pc.reset(vals=[1101,100,-1,4,0]), pc.run()
|
||||||
|
assert pc.data.toList() == [1101,100,-1,4,99]
|
||||||
|
pc.reset(vals=[3,9,8,9,10,9,4,9,99,-1,8]), pc.run()
|
||||||
|
assert pc.data[0] == 0
|
||||||
|
pc.reset(input=8), pc.run()
|
||||||
|
assert pc.data[0] == 1
|
||||||
|
pc.reset(vals=[3,9,7,9,10,9,4,9,99,-1,8], input=0), pc.run()
|
||||||
|
assert pc.data[0] == 1
|
||||||
|
pc.reset(input=8), pc.run()
|
||||||
|
assert pc.data[0] == 0
|
||||||
|
pc.reset(vals=[3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9]), pc.run()
|
||||||
|
assert pc.data[0] == 0
|
||||||
|
pc.reset(input=1), pc.run()
|
||||||
|
assert pc.data[0] == 1
|
||||||
|
pc.reset(vals=[3,3,1105,-1,9,1101,0,0,12,4,12,99,1]), pc.run()
|
||||||
|
assert pc.data[0] == 0
|
||||||
|
pc.reset(input=1), pc.run()
|
||||||
|
assert pc.data[0] == 1
|
||||||
|
pc.reset(vals=[3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,
|
||||||
|
1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,999,1105,1,46,
|
||||||
|
1101,1000,1,20,4,20,1105,1,46,98,99]), pc.run()
|
||||||
|
assert pc.data[0] == 999
|
||||||
|
pc.reset(input=8), pc.run()
|
||||||
|
assert pc.data[0] == 1000
|
||||||
|
pc.reset(input=9), pc.run()
|
||||||
|
assert pc.data[0] == 1001
|
||||||
|
|
||||||
|
def test_09():
|
||||||
|
pc = intcode.Computer([104,1125899906842624,99])
|
||||||
|
pc.run()
|
||||||
|
assert pc.data[0] == 1125899906842624
|
||||||
|
pc.reset(vals=[1102,34915192,34915192,7,4,7,99,0]), pc.run()
|
||||||
|
assert len(str(pc.data[0])) == 16
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
test_02()
|
||||||
|
test_05()
|
||||||
|
test_09()
|
Loading…
x
Reference in New Issue
Block a user