summaryrefslogtreecommitdiff
path: root/2024/17/python/main.py
blob: a441d4010c9d721d9ff60796f4c868eb033e124b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
from fileinput import input
from itertools import takewhile, zip_longest

inp = map(str.strip, input())
regs = [int(r[2]) for r in (line.split() for line in takewhile(bool, inp))]
prog = [int(o) for o in next(inp).split()[1].split(",")]
out = []


def run(prog, ra, rb, rc):
    out = []
    ir = 0
    while ir < len(prog):
        instr, op = prog[ir], prog[ir + 1]
        combo = {4: ra, 5: rb, 6: rc}
        cop = combo.get(op, op)
        match instr:
            case 0:
                ra = ra >> cop
            case 1:
                rb ^= op
            case 2:
                rb = cop & 0b111
            case 3 if ra:
                ir = op - 2
            case 4:
                rb ^= rc
            case 5:
                yield cop & 0b111
            case 6:
                rb = ra >> cop
            case 7:
                rc = ra >> cop
        ir += 2
    return out


def match(prog, ra):
    return (
        got == want
        for got, want in zip_longest(
            reversed(list(run(prog, ra, 0, 0))),
            reversed(prog),
        )
    )


def find_a(prog):
    q = list(range(8))
    while True:
        curr = q.pop(0)
        if all(match(prog, curr)):
            return curr

        best = sum(match(prog, curr))
        for n in range(8):
            ra = (curr << 3) + n
            if sum(match(prog, ra)) > best:
                q.append(ra)


silver = ",".join(map(str, run(prog, *regs)))
gold = find_a(prog)

print("silver:", silver)
print("gold:", gold)