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 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): class Day(AOCDay):
inputs = [ inputs = [
[ [
@ -18,22 +31,21 @@ class Day(AOCDay):
] ]
] ]
def part1(self): def get_fuel(self, part2: bool = False):
fuel_sum = 0 if len(self.input) == 1:
for x in self.getInputListAsType(int): return get_fuel(self.getInput(int), part2)
fuel_sum += x // 3 - 2 else:
fuel_sum = 0
for x in self.getInput(int):
fuel_sum += get_fuel(x, part2)
return fuel_sum return fuel_sum
def part1(self):
return self.get_fuel()
def part2(self): def part2(self):
fuel_sum = 0 return self.get_fuel(True)
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
if __name__ == '__main__': if __name__ == '__main__':

View File

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

View File

@ -24,12 +24,12 @@ class Day(AOCDay):
hull = Grid() hull = Grid()
face = 0 face = 0
pos = Coordinate(0, 0) pos = Coordinate(0, 0)
painted = {} painted = set()
while not comp.isHalted(): while not comp.isHalted():
comp.addInput(hull.isSet(pos)) comp.addInput(int(hull.isSet(pos)))
hull.set(pos, comp.getOutput()) hull.set(pos, comp.getOutput())
painted[pos] = True painted.add(pos)
face += 1 if comp.getOutput() else -1 face += 1 if comp.getOutput() else -1
pos = pos + MOVEMENTS[face % 4] pos = pos + MOVEMENTS[face % 4]
@ -50,13 +50,7 @@ class Day(AOCDay):
face += 1 if comp.getOutput() else -1 face += 1 if comp.getOutput() else -1
pos = pos + MOVEMENTS[face % 4] pos = pos + MOVEMENTS[face % 4]
hull.transform(GridTransformation.ROTATE_RIGHT) hull.print(true_char='#', false_char=' ')
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()
return "see image above" return "see image above"

View File

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

View File

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