diff --git a/2020/Day 8/Solution - with threads.py b/2020/Day 8/Solution - with threads.py new file mode 100644 index 0000000..8ece44e --- /dev/null +++ b/2020/Day 8/Solution - with threads.py @@ -0,0 +1,73 @@ +from threading import Thread, current_thread, main_thread + +input_file = "input.txt" + +threads = [] + + +def run_file(current_line=0, explored_lines=None, accumulator=0, switch=False): + """ + Run the program contained in the eponymous list. If switch is True, try and correct the program + to be able to complete it on other threads. Otherwise, exit on program end or repeated instruction. + :param current_line: Position to start at in the program (Program Counter) + :param explored_lines: Array of already executed instructions, to detect repeats + :param accumulator: Starting value of the accumulator + :param switch: If True, try to switch a nop to a jmp or vice-versa to fix the program + :return: True if booted successfully or if a correction allowed to boot. + """ + if explored_lines is None: + explored_lines = list() + + while current_line <= len(program) - 1: + if current_line in explored_lines: + print(f"Instruciton at line {current_line} would have been executed twice.\n" + f"The accumulator value at this point was {accumulator}") + return False + + instruction, argument = program[current_line].split(" ") + explored_lines.append(current_line) + + if instruction == "jmp": + if switch: + # Simulate nop by copying the current state and adding one the the current_line + threads.append(Thread(name=str(current_line), target=run_file, + args=(current_line+1, explored_lines.copy(), accumulator))) + threads[-1].start() + + current_line += int(argument) + + elif instruction == "nop": + if switch: + # Simulate a jump by copying the current state but adding the current argument to the current_line + threads.append(Thread(name=str(current_line), target=run_file, + args=(current_line+int(argument), explored_lines.copy(), accumulator))) + threads[-1].start() + + current_line += 1 + + elif instruction == "acc": + accumulator += int(argument) + current_line += 1 + + print(f"Booted successfully !\nThe final accumulator value was {accumulator}") + if current_thread() != main_thread(): + print(f"The boot was possible thanks to a modification on line {current_thread().name}") + + return True + + +program = [] + + +with open(input_file) as instructions: + line = instructions.readline() + while line and line != "\n": + line = line.strip("\n") + program.append(line) + line = instructions.readline() + +run_file(switch=True) + +# Wait for children to terminate +for thread in threads: + thread.join()