···11+import fileinput
22+from utils import parse_nums
33+44+55+def simulate(program, a, b, c):
66+ pc = 0
77+ out = []
88+99+ while pc < len(program):
1010+ opcode, literal = program[pc:pc+2]
1111+1212+ if literal <= 3:
1313+ combo = literal
1414+ elif literal == 4:
1515+ combo = a
1616+ elif literal == 5:
1717+ combo = b
1818+ elif literal == 6:
1919+ combo = c
2020+2121+ if opcode == 0:
2222+ a = a // (2 ** combo)
2323+ elif opcode == 1:
2424+ b ^= literal
2525+ elif opcode == 2:
2626+ b = combo % 8
2727+ elif opcode == 3:
2828+ if a != 0:
2929+ pc = literal * 2
3030+ continue
3131+ elif opcode == 4:
3232+ b ^= c
3333+ elif opcode == 5:
3434+ out.append(combo % 8)
3535+ elif opcode == 6:
3636+ b = a // (2 ** combo)
3737+ elif opcode == 7:
3838+ c = a // (2 ** combo)
3939+4040+ pc += 2
4141+4242+ return out
4343+4444+4545+# Read problem input.
4646+for i, line in enumerate(fileinput.input()):
4747+ if i == 0:
4848+ A = parse_nums(line)[0]
4949+ elif i == 1:
5050+ B = parse_nums(line)[0]
5151+ elif i == 2:
5252+ C = parse_nums(line)[0]
5353+ elif i == 4:
5454+ PROGRAM = parse_nums(line)
5555+5656+5757+# Simulate the program for part 1.
5858+part_1 = simulate(PROGRAM, A, B, C)
5959+print("Part 1:", ','.join(str(n) for n in part_1))
6060+6161+6262+# Solve part 2.
6363+#
6464+# For the problem input, note that each "output byte" is affected
6565+# by a byte in order of the starting A register. You can manually
6666+# dial in some of the high bytes of the starting value to narrow
6767+# the search space until it's something viable to be simulated.
6868+start = 0o5322350130000000
6969+for s in range(start, start + 10000000):
7070+ out = []
7171+ A = s
7272+ B = 0
7373+ C = 0
7474+ while True:
7575+ B = A % 8
7676+ B ^= 2
7777+ C = (A // (2**B))
7878+ A >>= 3
7979+ B ^= C
8080+ B ^= 7
8181+ out.append(B % 8)
8282+ if A == 0:
8383+ break
8484+8585+ if out == PROGRAM:
8686+ print("Part 2:", s)
8787+ break