intcode programs running again, but horribly slow

This commit is contained in:
Stefan Harmuth 2022-12-10 08:51:05 +01:00
parent b9c38b72bd
commit e3b847bdf6
5 changed files with 85 additions and 67 deletions

View File

@ -1,6 +1,19 @@
from tools.aoc import AOCDay
def get_fuel(count: int, part2: bool = False):
if not part2:
return count // 3 - 2
else:
fuel_sum = 0
count = count // 3 - 2
while count > 0:
fuel_sum += count
count = count // 3 - 2
return fuel_sum
class Day(AOCDay):
inputs = [
[
@ -18,22 +31,21 @@ class Day(AOCDay):
]
]
def part1(self):
def get_fuel(self, part2: bool = False):
if len(self.input) == 1:
return get_fuel(self.getInput(int), part2)
else:
fuel_sum = 0
for x in self.getInputListAsType(int):
fuel_sum += x // 3 - 2
for x in self.getInput(int):
fuel_sum += get_fuel(x, part2)
return fuel_sum
def part1(self):
return self.get_fuel()
def part2(self):
fuel_sum = 0
for x in self.getInputListAsType(int):
fuel_add = x // 3 - 2
while fuel_add > 0:
fuel_sum += fuel_add
fuel_add = fuel_add // 3 - 2
return fuel_sum
return self.get_fuel(True)
if __name__ == '__main__':

View File

@ -7,7 +7,7 @@ from typing import Any, List
def get_comps(memory: List[int]) -> List[IntCode]:
comps = []
for _ in range(5):
comps.append(IntCode(memory.copy()))
comps.append(IntCode(memory))
return comps
@ -41,7 +41,7 @@ class Day(AOCDay):
comps[i].addInput(input1)
comps[i].addInput(input2)
comps[i].run()
comps[i].start()
signal = comps[4].getOutput()
if signal > max_signal:
@ -54,7 +54,7 @@ class Day(AOCDay):
max_signal = 0
phase_settings = [5, 6, 7, 8, 9]
for s in itertools.permutations(phase_settings):
comps = get_comps(init_memory.copy())
comps = get_comps(init_memory)
for i, input1 in enumerate(s):
if i == 0 and not comps[i].isRunning():

View File

@ -24,12 +24,12 @@ class Day(AOCDay):
hull = Grid()
face = 0
pos = Coordinate(0, 0)
painted = {}
painted = set()
while not comp.isHalted():
comp.addInput(hull.isSet(pos))
comp.addInput(int(hull.isSet(pos)))
hull.set(pos, comp.getOutput())
painted[pos] = True
painted.add(pos)
face += 1 if comp.getOutput() else -1
pos = pos + MOVEMENTS[face % 4]
@ -50,13 +50,7 @@ class Day(AOCDay):
face += 1 if comp.getOutput() else -1
pos = pos + MOVEMENTS[face % 4]
hull.transform(GridTransformation.ROTATE_RIGHT)
hull.transform(GridTransformation.FLIP_HORIZONTALLY)
for x in range(hull.minX, hull.maxX + 1):
for y in range(hull.minY, hull.maxY + 1):
print("#" if hull.isSet(Coordinate(x, y)) else " ", end="")
print()
hull.print(true_char='#', false_char=' ')
return "see image above"

View File

@ -20,10 +20,20 @@ class Moon:
self.y = y
self.z = z
def getKineticEnergy(self):
return abs(self.vel_x) + abs(self.vel_y) + abs(self.vel_z)
def getPotentialEnergy(self):
return abs(self.x) + abs(self.y) + abs(self.z)
def getEnergy(self):
potential = abs(self.x) + abs(self.y) + abs(self.z)
kinetic = abs(self.vel_x) + abs(self.vel_y) + abs(self.vel_z)
return potential * kinetic
return self.getPotentialEnergy() * self.getKineticEnergy()
def __str__(self):
return "x=%3d y=%3d z=%3d" % (self.x, self.y, self.z)
def __repr__(self):
return str(self)
def moveMoons(moons: List[Moon]):
@ -50,7 +60,7 @@ class Day(AOCDay):
(12644, "input12")
],
[
# ??? (2772, "test_input12"),
(2772, "test_input12"),
(4686774924, "test_input12_2"),
(None, "input12")
]
@ -66,21 +76,20 @@ class Day(AOCDay):
def part2(self) -> Any:
moons = [Moon(*map(int, findall(scanline_regex, line)[0])) for line in self.getInput()]
init_moons = moons.copy()
vel_0_pos = [0, 0, 0, 0]
init_moons = [Moon(*map(int, findall(scanline_regex, line)[0])) for line in self.getInput()]
vel_0_pos = [0] * len(moons)
moveCounter = 0
#while 0 in vel_0_pos:
for bla in range(3000):
while 0 in vel_0_pos:
moveCounter += 1
moveMoons(moons)
for i, m in enumerate(moons):
if m.x == init_moons[i].x and m.y == init_moons[i].y and m.z == init_moons[i].z and m.vel_x == 0 and m.vel_y == 0 and m.vel_z == 0:
print(i, moveCounter)
if (vel_0_pos[i] == 0 or vel_0_pos[i] > moveCounter - vel_0_pos[i]) and m.vel_x == 0 and m.vel_y == 0 and m.vel_z == 0:
vel_0_pos[i] = moveCounter - vel_0_pos[i]
if m.x == init_moons[i].x and m.y == init_moons[i].y and m.z == init_moons[i].z:
# if i == 1:
# print("init pos:", i, "after", moveCounter, "moves =>", m.getPotentialEnergy(), m.getKineticEnergy())
if m.getKineticEnergy() == 0:
print("init state:", i, "after", moveCounter, "moves =>", m.getPotentialEnergy())
vel_0_pos[i] = moveCounter
print(vel_0_pos)
return lcm(*vel_0_pos)

View File

@ -1,7 +1,8 @@
import threading
import time
from collections import deque, defaultdict
from enum import Enum
from queue import Queue
from typing import List, Union
from typing import List
class IntCodeState(Enum):
@ -10,26 +11,35 @@ class IntCodeState(Enum):
HALTED = 2
def _get_from_queue(queue: deque, count: int = 1, timeout: int = 10) -> int | List[int] | None:
started = time.perf_counter()
while len(queue) < count:
time.sleep(0.0001)
if time.perf_counter() - started > timeout:
raise TimeoutError()
if count == 1:
return queue.popleft()
else:
return [queue.popleft() for _ in range(count)]
class IntCode(threading.Thread):
def __init__(self, memory: List[int]):
super().__init__()
self.instr_ptr = 0
self.memory = memory
self.input_queue = Queue()
self.output_queue = Queue()
self.memory = defaultdict(int)
for i, v in enumerate(memory):
self.memory[i] = v
self.input_queue = deque()
self.output_queue = deque()
self.state = IntCodeState.INITIALIZED
self.relative_base = 0
def getMemoryValue(self, address: int) -> int:
if address > len(self.memory) - 1:
self.memory.extend([0] * (address - len(self.memory) + 1))
return self.memory[address]
def setMemoryValue(self, address: int, value: int):
if address > len(self.memory) - 1:
self.memory.extend([0] * (address - len(self.memory) + 1))
self.memory[address] = value
def getParameterValue(self, address: int, mode: int = 0) -> int:
@ -52,26 +62,20 @@ class IntCode(threading.Thread):
def isHalted(self):
return self.state == IntCodeState.HALTED
def sendOutputTo(self, target_queue: Queue):
def sendOutputTo(self, target_queue: deque):
self.output_queue = target_queue
def addInput(self, value: int):
self.input_queue.put(value)
self.input_queue.append(value)
def hasOutput(self):
return self.output_queue.qsize() > 0
return len(self.output_queue) > 0
def getOutput(self, count: int = 1, block: bool = True, timeout: int = None) -> Union[int, List[int]]:
if count == 1:
res = self.output_queue.get(block=block, timeout=timeout)
self.output_queue.task_done()
else:
res = []
for _ in range(count):
res.append(self.output_queue.get(block=block, timeout=timeout))
self.output_queue.task_done()
def getOutput(self, count: int = 1, timeout: int = 10) -> int | List[int] | None:
return _get_from_queue(self.output_queue, count, timeout)
return res
def getInput(self, count: int = 1, timeout: int = 10) -> int | List[int] | None:
return _get_from_queue(self.input_queue, count, timeout)
def run(self):
self.state = IntCodeState.RUNNING
@ -96,11 +100,10 @@ class IntCode(threading.Thread):
self.instr_ptr += 4
elif op_code == 3: # input
target_addr = self.getTargetAddress(self.instr_ptr + 1, p1_mode)
self.setMemoryValue(target_addr, self.input_queue.get(timeout=30))
self.input_queue.task_done()
self.setMemoryValue(target_addr, self.getInput())
self.instr_ptr += 2
elif op_code == 4: # output
self.output_queue.put(self.getParameterValue(self.instr_ptr + 1, p1_mode))
self.output_queue.append(self.getParameterValue(self.instr_ptr + 1, p1_mode))
self.instr_ptr += 2
elif op_code == 5: # jump-if-true
if self.getParameterValue(self.instr_ptr + 1, p1_mode) != 0: