day07, welcome back to threaded intcode computers \o/

This commit is contained in:
Stefan Harmuth 2021-11-27 18:11:05 +01:00
parent 8e397e4442
commit e3a8fb64e6
9 changed files with 132 additions and 16 deletions

View File

@ -9,16 +9,18 @@ class Day(AOCDay):
def part1(self) -> Any:
comp = IntCode(self.getInputAsArraySplit(",", int))
comp.input.put(1)
comp.run()
comp.addInput(1)
comp.start()
while True:
if (check := comp.output.get()) != 0:
if (check := comp.getOutput()) != 0:
comp.join()
return check
def part2(self) -> Any:
comp = IntCode(self.getInputAsArraySplit(",", int))
comp.input.put(5)
comp.run()
comp.addInput(5)
comp.start()
while True:
if (check := comp.output.get()) != 0:
if (check := comp.getOutput()) != 0:
comp.join()
return check

72
day07.py Normal file
View File

@ -0,0 +1,72 @@
import itertools
from aoc import AOCDay
from intcode import IntCode
from typing import Any, List
def get_comps(memory: List[int]) -> List[IntCode]:
comps = []
for _ in range(5):
comps.append(IntCode(memory.copy()))
return comps
class Day(AOCDay):
test_solutions_p1 = [43210, 54321, 65210]
test_solutions_p2 = [139629729, 18216]
def part1(self) -> Any:
init_memory = self.getInputAsArraySplit(",", int)
max_signal = 0
phase_settings = [0, 1, 2, 3, 4]
for s in itertools.permutations(phase_settings):
comps = get_comps(init_memory)
for i, input1 in enumerate(s):
if i == 0:
input2 = 0
else:
input2 = comps[i-1].getOutput()
comps[i].addInput(input1)
comps[i].addInput(input2)
comps[i].run()
signal = comps[4].getOutput()
if signal > max_signal:
max_signal = signal
return max_signal
def part2(self) -> Any:
init_memory = self.getInputAsArraySplit(",", int)
max_signal = 0
phase_settings = [5, 6, 7, 8, 9]
for s in itertools.permutations(phase_settings):
comps = get_comps(init_memory.copy())
for i, input1 in enumerate(s):
if i == 0 and not comps[i].isRunning():
input2 = 0
else:
input2 = comps[i-1].getOutput()
comps[i].addInput(input1)
comps[i].addInput(input2)
comps[i].start()
while not comps[4].isHalted():
for i in range(5):
if not comps[i].isHalted() and not comps[i-1].isHalted():
comps[i].addInput(comps[i-1].getOutput())
signal = comps[4].getOutput()
if signal > max_signal:
max_signal = signal
for i in range(5):
comps[i].join()
return max_signal

1
inputs/input07 Normal file
View File

@ -0,0 +1 @@
3,8,1001,8,10,8,105,1,0,0,21,38,59,76,89,106,187,268,349,430,99999,3,9,1002,9,3,9,101,2,9,9,1002,9,4,9,4,9,99,3,9,1001,9,5,9,1002,9,5,9,1001,9,2,9,1002,9,3,9,4,9,99,3,9,1001,9,4,9,102,4,9,9,1001,9,3,9,4,9,99,3,9,101,4,9,9,1002,9,5,9,4,9,99,3,9,1002,9,3,9,101,5,9,9,1002,9,3,9,4,9,99,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,99,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,101,1,9,9,4,9,99,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,99

1
inputs/test_input07_1_0 Normal file
View File

@ -0,0 +1 @@
3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0

1
inputs/test_input07_1_1 Normal file
View File

@ -0,0 +1 @@
3,23,3,24,1002,24,10,24,1002,23,-1,23,101,5,23,23,1,24,23,23,4,23,99,0,0

1
inputs/test_input07_1_2 Normal file
View File

@ -0,0 +1 @@
3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33,1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0

1
inputs/test_input07_2_0 Normal file
View File

@ -0,0 +1 @@
3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26,27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5

1
inputs/test_input07_2_1 Normal file
View File

@ -0,0 +1 @@
3,52,1001,52,-5,52,3,53,1,52,56,54,1007,54,5,55,1005,55,26,1001,54,-5,54,1105,1,12,1,53,54,53,1008,54,0,55,1001,55,1,55,2,53,55,53,4,53,1001,56,-1,56,1005,56,6,99,0,0,0,0,10

View File

@ -1,14 +1,23 @@
from typing import List
from enum import Enum
from queue import Queue
import threading
from typing import List, Union
class IntCode:
class IntCodeState(Enum):
INITIALIZED = 0
RUNNING = 1
HALTED = 2
class IntCode(threading.Thread):
def __init__(self, memory: List[int], mem_size: int = 0):
super().__init__()
self.instr_ptr = 0
self.halted = False
self.memory = memory
self.input = Queue()
self.output = Queue()
self.input_queue = Queue()
self.output_queue = Queue()
self.state = IntCodeState.INITIALIZED
if len(self.memory) < mem_size:
self.memory.extend([0] * (mem_size - len(self.memory)))
@ -18,8 +27,33 @@ class IntCode:
elif mode == 1:
return self.memory[address]
def isRunning(self):
return self.state == IntCodeState.RUNNING
def isHalted(self):
return self.state == IntCodeState.HALTED
def sendOutputTo(self, target_queue: Queue):
self.output_queue = target_queue
def addInput(self, value: int):
self.input_queue.put(value)
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()
return res
def run(self):
while not self.halted:
self.state = IntCodeState.RUNNING
while not self.isHalted():
instr = self.memory[self.instr_ptr] % 100
p1_mode = self.memory[self.instr_ptr] // 100 % 10
p2_mode = self.memory[self.instr_ptr] // 1_000 % 10
@ -38,11 +72,12 @@ class IntCode:
self.memory[target_addr] = param1 * param2
self.instr_ptr += 4
elif instr == 3: # input
target_addr = self.memory[self.instr_ptr + 3]
self.memory[target_addr] = self.input.get()
target_addr = self.memory[self.instr_ptr + 1]
self.memory[target_addr] = self.input_queue.get()
self.input_queue.task_done()
self.instr_ptr += 2
elif instr == 4: # output
self.output.put(self.get_parameter_value(self.instr_ptr + 1, p1_mode))
self.output_queue.put(self.get_parameter_value(self.instr_ptr + 1, p1_mode))
self.instr_ptr += 2
elif instr == 5: # jump-if-true
if self.get_parameter_value(self.instr_ptr + 1, p1_mode) != 0:
@ -67,6 +102,7 @@ class IntCode:
self.memory[target_addr] = param1 == param2
self.instr_ptr += 4
elif instr == 99:
self.halted = True
self.state = IntCodeState.HALTED
return
else:
raise ValueError("Invalid instruction encountered at pos %d: %d" % (self.instr_ptr, instr))