Day 23 - Safe Cracking

This was fun: there was a similar problem in 2018, Day 19, and I mostly solved that one by hand. With this problem, I figured I could make a React app to step through the program.

One of the key things when stepping through things, rather than just be able to “step through n times,” it was useful to run until I reached a certain instruction or until a certain register was 0. That is, I needed custom “break points” within the program.

Once that was added, I ticked through to see how the program ran. I was able to determine what the loops were doing. After the first main loop, the program would continue running, decrementing c by 2 until it was 0. Each time, it’d take the value of a and multiply it by b and store that back in a.

After one loop, my registers look like:

132 10 20 0

So I knew that after the next loop, a would be 132 * 10 = 1320. After that, 1320 * 9 = 11880, and so on. If the program was actually running, these steps are what took so long (around 500 million steps). So I was able to skip over a lot of the computational expensive parts of the program:

1320 9 18 0
11880 8 16 0
95040 7 14 0
665280 6 12 0
3991680 5 10 0
19958400 4 8 0
79833600 3 6 0
239500800 2 4 0
479001600 1 2 0

Starting with these ending registers (and the necessary operations toggled to their new states), the rest of the program ran fairly quickly to give me my answer for part two.

To run this yourself, the application works as follows:

When the app starts, you’ll need to initialize it with your program. Paste in your program’s input and submit to start the program. It defaults to the input I received.

Press the play button (▶) to run the program until the break point. If no point is set, it’ll run until the program finishes. The steps under the play button step forward 1, 10, and 100 ticks, respectively.

The break point can be any expression that’ll be eval‘d. Use a, b, c, d variables for the registers, and i for the instruction. For instance, to run until the program is at instruction 16, just enter i === 16 into the breakpoint. To run until it is at instruction 16 and register d is equal to 0, then you’d have i === 16 && d === 0.

At the top, you can change any register to any value, change what instruction the program is at by typing in i, and can even change arbitrary lines by typing in l. Once you type in the action, press set to save the change.

For instance, before I started running the program, I had to change register a to 12, away from its part one initial value of 7.

As always, code is untranspiled: modern browsers only.

Day 23, Part 1 Description

--- Day 23: Safe Cracking ---

This is one of the top floors of the nicest tower in EBHQ. The Easter Bunny's private office is here, complete with a safe hidden behind a painting, and who wouldn't hide a star in a safe behind a painting?

The safe has a digital screen and keypad for code entry. A sticky note attached to the safe has a password hint on it: "eggs". The painting is of a large rabbit coloring some eggs. You see 7.

When you go to type the code, though, nothing appears on the display; instead, the keypad comes apart in your hands, apparently having been smashed. Behind it is some kind of socket - one that matches a connector in your prototype computer! You pull apart the smashed keypad and extract the logic circuit, plug it into your computer, and plug your computer into the safe.

Now, you just need to figure out what output the keypad would have sent to the safe. You extract the assembunny code from the logic chip (your puzzle input).

The code looks like it uses almost the same architecture and instruction set that the monorail computer used! You should be able to use the same assembunny interpreter for this as you did there, but with one new instruction:

tgl x toggles the instruction x away (pointing at instructions like jnz does: positive means forward; negative means backward):

For example, given this program:

cpy 2 a
tgl a
tgl a
tgl a
cpy 1 a
dec a
dec a

In this example, the final value in register a is 3.

The rest of the electronics seem to place the keypad entry (the number of eggs, 7) in register a, run the code, and then send the value left in register a to the safe.

What value should be sent to the safe?

Answer to Part One

12663

Day 23, Part 2 Description

--- Part Two ---

The safe doesn't open, but it does make several angry noises to express its frustration.

You're quite sure your logic is working correctly, so the only other thing is... you check the painting again. As it turns out, colored eggs are still eggs. Now you count 12.

As you run the program with this new input, the prototype computer begins to overheat. You wonder what's taking so long, and whether the lack of any instruction more powerful than "add one" has anything to do with it. Don't bunnies usually multiply?

Anyway, what value should actually be sent to the safe?

Answer to Part Two

479009223


Interactive Application 💻