Spaces:
Running
Running
from ast import literal_eval | |
def load_data(file): | |
with open(file) as f: | |
data = f.readlines() | |
registers = {} | |
for line in data: | |
line = line.strip("\n") | |
if "A" in line: | |
registers["A"] = int(line.split(" ")[-1]) | |
if "B" in line: | |
registers["B"] = int(line.split(" ")[-1]) | |
if "C" in line: | |
registers["C"] = int(line.split(" ")[-1]) | |
if "Program" in line: | |
program = [int(c) for c in line.split(" ")[-1].split(",")] | |
return registers, program | |
class Computer: | |
def __init__(self, registers, program): | |
self.OPS = { | |
0: "adv", | |
1: "bxl", | |
2: "bst", | |
3: "jnz", | |
4: "bxc", | |
5: "out", | |
6: "bdv", | |
7: "cdv", | |
} | |
self.registers = registers | |
self.program = program | |
self.instruction_pointer = 0 | |
self.outputs = [] | |
def combo(self, operand): | |
if 0 <= operand <= 3: | |
return operand | |
elif operand == 4: | |
return self.registers["A"] | |
elif operand == 5: | |
return self.registers["B"] | |
elif operand == 6: | |
return self.registers["C"] | |
elif operand == 7: | |
raise ValueError("Reserved!") | |
else: | |
raise ValueError("Unknown") | |
def adv(self, operand): | |
combo = self.combo(operand) | |
numerator = self.registers["A"] | |
denominator = 2 ** combo | |
self.registers["A"] = int(numerator / denominator) | |
def bxl(self, operand): | |
self.registers["B"] = self.registers["B"] ^ operand | |
def bst(self, operand): | |
self.registers["B"] = self.combo(operand) % 8 | |
def jnz(self, operand): | |
if self.registers["A"] == 0: | |
return | |
self.instruction_pointer = operand - 2 | |
def bxc(self, operand): | |
self.registers["B"] = self.registers["B"] ^ self.registers["C"] | |
def out(self, operand): | |
combo = self.combo(operand) | |
self.outputs.append(combo % 8) | |
def bdv(self, operand): | |
combo = self.combo(operand) | |
numerator = self.register["A"] | |
denominator = 2 ** combo | |
self.registers["B"] = int(numerator / denominator) | |
def cdv(self, operand): | |
combo = self.combo(operand) | |
numerator = self.registers["A"] | |
denominator = 2 ** combo | |
self.registers["C"] = int(numerator / denominator) | |
def evaluate(self, instruction, operand): | |
op = self.OPS[instruction] | |
if op == "adv": | |
return self.adv(operand) | |
elif op == "bxl": | |
return self.bxl(operand) | |
elif op == "bst": | |
return self.bst(operand) | |
elif op == "jnz": | |
return self.jnz(operand) | |
elif op == "bxc": | |
return self.bxc(operand) | |
elif op == "out": | |
return self.out(operand) | |
elif op == "bdv": | |
return self.bdv(operand) | |
elif op == "cdv": | |
return self.cdv(operand) | |
else: | |
raise ValueError(f"Uknown op: {op}") | |
def get_next_instruction_and_operand(self): | |
instruction, operand = self.program[self.instruction_pointer], self.program[self.instruction_pointer+1] | |
return instruction, operand | |
def step(self): | |
while self.instruction_pointer < len(program): | |
inst, operand = self.get_next_instruction_and_operand() | |
self.evaluate(inst, operand) | |
self.instruction_pointer += 2 | |
# print("Halt") | |
# print("Outputs: ", ",".join([str(out) for out in self.outputs])) | |
return self.outputs | |
registers, program = load_data("input.txt") | |
# print(registers, program) | |
computer = Computer(registers.copy(), program) | |
outputs = computer.step() | |
print(",".join([str(out) for out in outputs])) | |
## Part 2 | |
# # Tried Brute force, ran all night, didnt produce an answer. | |
# # Halt program as soon as output not equal program | |
# # There's probably a smarter way... | |
# | |
# class Computer2(Computer): | |
# def step(self): | |
# | |
# while self.instruction_pointer < len(program): | |
# inst, operand = self.get_next_instruction_and_operand() | |
# self.evaluate(inst, operand) | |
# self.instruction_pointer += 2 | |
# | |
# if len(self.outputs) > 0: | |
# for out, prog in zip(self.outputs, self.program): | |
# if out != prog: | |
# return | |
# | |
# # print("Halt") | |
# # print("Outputs: ", ",".join([str(out) for out in self.outputs])) | |
# return self.outputs | |
# | |
# registers, program = load_data("input.txt") | |
# | |
# | |
# # A = 4063000000 Reached here with brute force | |
# A = 0 | |
# while True: | |
# if A % 100000 == 0: | |
# print(A) | |
# input_registers = registers.copy() | |
# input_registers["A"] = A | |
# computer = Computer2(input_registers, program) | |
# outputs = computer.step() | |
# | |
# if outputs == program: | |
# print("DONE") | |
# break | |
# | |
# else: | |
# A += 1 | |
# | |
# print(A) | |