Intro

Day 7 brings another Intcode puzzle, so I finally bit the bullet and refactored my vm. I’m writing this after reading the prompt for day 9, so I’m getting the sense more refactoring might be coming soon. For now, let’s cover day 7’s solution.

As always, you can find my full solutions repo here.

Solution

The main thing I’ve done to refactor my Intcode vm is to encapsulate it inside a class. The instance will now keep track of the program counter and the internal memory/program. The primary interface to the class is the compute(inputs) method, which takes a list of inputs and returns an output value and an associated code (“halt” or “output”). This problem requires you to use previous outputs as inputs to the next amp, so I had to modify the compute method accordingly.

With the new Intcode computer, the rest of the part one falls into place easily. Generate all permuations of amp settings and then iterate through them, using the vm to compute the max thrust.

phase_settings = list(permutations([0, 1, 2, 3, 4], 5))
max_thrust = -1
program = prep_intcode_program("./input/day7.txt")

for amp_config in phase_settings:
    line_in = 0
    for amp in amp_config:
        computer = IntcodeComputer(program.copy())
        line_in, halt_type = computer.compute([amp, line_in])
        line_in = line_in
    if line_in > max_thrust:
        max_thrust = line_in

The second part throws a wrench into the puzzle by requiring you to pass one amp’s output into the next amp’s input. This is the spec change that made me have to do a refactor that allowed for output but retained the instance’s program counter.

I’m using the same general approach of iterating through possibile amp configurations and comparing the final 5th amp output to the max seen thusfar. This is pretty messy, but I’m getting shit done over here.

for amp_config in phase_settings:
    first_run = True
    found = False
    amps = [IntcodeComputer(program.copy()) for i in range(0, 5)]
    amp_id = 0
    last_e_signal = -1
    line_in = 0

    while not found or amp_id != 0:
        if first_run:
            line_in = [amp_config[amp_id], line_in]
        else:
            line_in = [line_in]

        line_in, halt_type = amps[amp_id].compute(line_in)

        if halt_type == "output" and amp_id == 4:
            last_e_signal = line_in

        if halt_type == "halt":
            found = True

        if amp_id == 4:
            first_run = False

        amp_id = (amp_id + 1) % 5

    if last_e_signal > max_thrust:
        max_thrust = last_e_signal

Hopefully this version of the Intcode vm will be more extensible for future Intcode puzzles.

As always, you can find my full solutions repo here.