day07, welcome back to threaded intcode computers \o/
This commit is contained in:
parent
8e397e4442
commit
e3a8fb64e6
14
day05.py
14
day05.py
@ -9,16 +9,18 @@ class Day(AOCDay):
|
|||||||
|
|
||||||
def part1(self) -> Any:
|
def part1(self) -> Any:
|
||||||
comp = IntCode(self.getInputAsArraySplit(",", int))
|
comp = IntCode(self.getInputAsArraySplit(",", int))
|
||||||
comp.input.put(1)
|
comp.addInput(1)
|
||||||
comp.run()
|
comp.start()
|
||||||
while True:
|
while True:
|
||||||
if (check := comp.output.get()) != 0:
|
if (check := comp.getOutput()) != 0:
|
||||||
|
comp.join()
|
||||||
return check
|
return check
|
||||||
|
|
||||||
def part2(self) -> Any:
|
def part2(self) -> Any:
|
||||||
comp = IntCode(self.getInputAsArraySplit(",", int))
|
comp = IntCode(self.getInputAsArraySplit(",", int))
|
||||||
comp.input.put(5)
|
comp.addInput(5)
|
||||||
comp.run()
|
comp.start()
|
||||||
while True:
|
while True:
|
||||||
if (check := comp.output.get()) != 0:
|
if (check := comp.getOutput()) != 0:
|
||||||
|
comp.join()
|
||||||
return check
|
return check
|
||||||
|
|||||||
72
day07.py
Normal file
72
day07.py
Normal 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
1
inputs/input07
Normal 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
1
inputs/test_input07_1_0
Normal 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
1
inputs/test_input07_1_1
Normal 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
1
inputs/test_input07_1_2
Normal 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
1
inputs/test_input07_2_0
Normal 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
1
inputs/test_input07_2_1
Normal 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
|
||||||
56
intcode.py
56
intcode.py
@ -1,14 +1,23 @@
|
|||||||
from typing import List
|
from enum import Enum
|
||||||
from queue import Queue
|
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):
|
def __init__(self, memory: List[int], mem_size: int = 0):
|
||||||
|
super().__init__()
|
||||||
self.instr_ptr = 0
|
self.instr_ptr = 0
|
||||||
self.halted = False
|
|
||||||
self.memory = memory
|
self.memory = memory
|
||||||
self.input = Queue()
|
self.input_queue = Queue()
|
||||||
self.output = Queue()
|
self.output_queue = Queue()
|
||||||
|
self.state = IntCodeState.INITIALIZED
|
||||||
if len(self.memory) < mem_size:
|
if len(self.memory) < mem_size:
|
||||||
self.memory.extend([0] * (mem_size - len(self.memory)))
|
self.memory.extend([0] * (mem_size - len(self.memory)))
|
||||||
|
|
||||||
@ -18,8 +27,33 @@ class IntCode:
|
|||||||
elif mode == 1:
|
elif mode == 1:
|
||||||
return self.memory[address]
|
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):
|
def run(self):
|
||||||
while not self.halted:
|
self.state = IntCodeState.RUNNING
|
||||||
|
while not self.isHalted():
|
||||||
instr = self.memory[self.instr_ptr] % 100
|
instr = self.memory[self.instr_ptr] % 100
|
||||||
p1_mode = self.memory[self.instr_ptr] // 100 % 10
|
p1_mode = self.memory[self.instr_ptr] // 100 % 10
|
||||||
p2_mode = self.memory[self.instr_ptr] // 1_000 % 10
|
p2_mode = self.memory[self.instr_ptr] // 1_000 % 10
|
||||||
@ -38,11 +72,12 @@ class IntCode:
|
|||||||
self.memory[target_addr] = param1 * param2
|
self.memory[target_addr] = param1 * param2
|
||||||
self.instr_ptr += 4
|
self.instr_ptr += 4
|
||||||
elif instr == 3: # input
|
elif instr == 3: # input
|
||||||
target_addr = self.memory[self.instr_ptr + 3]
|
target_addr = self.memory[self.instr_ptr + 1]
|
||||||
self.memory[target_addr] = self.input.get()
|
self.memory[target_addr] = self.input_queue.get()
|
||||||
|
self.input_queue.task_done()
|
||||||
self.instr_ptr += 2
|
self.instr_ptr += 2
|
||||||
elif instr == 4: # output
|
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
|
self.instr_ptr += 2
|
||||||
elif instr == 5: # jump-if-true
|
elif instr == 5: # jump-if-true
|
||||||
if self.get_parameter_value(self.instr_ptr + 1, p1_mode) != 0:
|
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.memory[target_addr] = param1 == param2
|
||||||
self.instr_ptr += 4
|
self.instr_ptr += 4
|
||||||
elif instr == 99:
|
elif instr == 99:
|
||||||
self.halted = True
|
self.state = IntCodeState.HALTED
|
||||||
|
return
|
||||||
else:
|
else:
|
||||||
raise ValueError("Invalid instruction encountered at pos %d: %d" % (self.instr_ptr, instr))
|
raise ValueError("Invalid instruction encountered at pos %d: %d" % (self.instr_ptr, instr))
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user