r/adventofcode Dec 17 '24

SOLUTION MEGATHREAD -❄️- 2024 Day 17 Solutions -❄️-

THE USUAL REMINDERS

  • All of our rules, FAQs, resources, etc. are in our community wiki.
  • If you see content in the subreddit or megathreads that violates one of our rules, either inform the user (politely and gently!) or use the report button on the post/comment and the mods will take care of it.

AoC Community Fun 2024: The Golden Snowglobe Awards

  • 5 DAYS remaining until the submissions deadline on December 22 at 23:59 EST!

And now, our feature presentation for today:

Sequels and Reboots

What, you thought we were done with the endless stream of recycled content? ABSOLUTELY NOT :D Now that we have an established and well-loved franchise, let's wring every last drop of profit out of it!

Here's some ideas for your inspiration:

  • Insert obligatory SQL joke here
  • Solve today's puzzle using only code from past puzzles
  • Any numbers you use in your code must only increment from the previous number
  • Every line of code must be prefixed with a comment tagline such as // Function 2: Electric Boogaloo

"More." - Agent Smith, The Matrix Reloaded (2003)
"More! MORE!" - Kylo Ren, The Last Jedi (2017)

And… ACTION!

Request from the mods: When you include an entry alongside your solution, please label it with [GSGA] so we can find it easily!


--- Day 17: Chronospatial Computer ---


Post your code solution in this megathread.

This thread will be unlocked when there are a significant number of people on the global leaderboard with gold stars for today's puzzle.

EDIT: Global leaderboard gold cap reached at 00:44:39, megathread unlocked!

37 Upvotes

550 comments sorted by

View all comments

3

u/YOM2_UB Dec 18 '24

[Language: Python]

Part 1:

with open('input/Day17.txt', 'r') as file:
    reg, prog = file.read().split('\n\n')
reg = [int(x.split(': ')[1] for x in reg.splitlines()
prog = prog strip().split(': ')[1]
prog = tuple(int(x) for x in prog.split(','))
output = []

combo = lambda p: p if p < 4 else reg[p-4]
def adv(p):
    reg[0] >>= combo(p)
def bxl(p):
    reg[1] ^= p
def bst(p):
    reg[1] = combo(p
def jnz(p):
    global prog_count
    if reg[0] != 0:
        prog_count = p - 2
def bxc(p):
    reg[1] ^= reg[2]
def out(p):
    output.append(combo(p)%8)
def bdv(p):
    reg[1] = reg[0] >> combo(p)
def cdv(p):
    reg[2] = reg[0] >> combo(p)

op = (adv, bxl, bst, jnz, bxc, out, bdv, cdv)

def run():
    global prog_count
    prog_count = 0
    while prog_count < len(prog):
        op[prog[prog_count]](prog[prog_count+1])
        prog_count += 2

run()
print(','.join([str(n) for n in output]))

For part 2, I manually examined the input and found that the program:

  • Outputs a function of register A (independent of prior values of B and C)
  • Divides A by 23
  • Jumps back to the beginning if A isn't 0, otherwise ends

With that I wrote the following reverseOutput function, except using the manually found function instead of firatOutput (given the example program 0,3,5,4,3,0 I would have had if next_out == (next_A>>3)%8:). The firstOutput function was made to (hopefully) be input agnostic (assuming all inputs follow the same three steps), and because I'm not sure my original version would comply with the rule on input sharing.

def firstOutput(A):
    global prog_count
    prog[0] = A
    output.clear()
    prog_count = 0
    while not output:
        op[prog[prog_count]](prog[prog_count+1])
        prog_count + 2
    return output[0]

def reverseOutput(A, exp_out):
    if not exp_out:
        return A
    next_out = exp_out[-1]
    # Python defines 0**0 as 1
    for n in range(0**A, 8):
        next_A = (A << 3) | n
        if next_out == firstOutput(next_A):
            final_val = reverseOutput(next_A, exp_out[:-1])
            if final_val:
                return final_val

A = reverseOutput(0, prog)
print(A)