44#
55
66import sys
7+ from collections import deque
78
89from aoc .common import InputData
910from aoc .common import SolutionBase
1819Output2 = int
1920
2021
21- TEST = """\
22+ TEST1 = """\
2223 Register A: 729
2324Register B: 0
2425Register C: 0
2526
2627Program: 0,1,5,4,3,0
2728"""
29+ TEST2 = """\
30+ Register A: 2024
31+ Register B: 0
32+ Register C: 0
33+
34+ Program: 0,3,5,4,3,0
35+ """
2836
2937
3038class Solution (SolutionBase [Input , Output1 , Output2 ]):
3139 def parse_input (self , input_data : InputData ) -> Input :
3240 return input_data
3341
34- def part_1 (self , input : Input ) -> Output1 :
42+ def run_program (self , lines : list [ str ] ) -> list [ str ] :
3543 def combo (operand : int ) -> str :
3644 match operand :
3745 case 0 | 1 | 2 | 3 :
@@ -41,7 +49,6 @@ def combo(operand: int) -> str:
4149 case _:
4250 raise ValueError
4351
44- lines = list (input )
4552 ins = []
4653 ip_map = dict [int , int ]()
4754 ins .append (Instruction .SET ("A" , lines [0 ][12 :]))
@@ -52,7 +59,6 @@ def combo(operand: int) -> str:
5259 for i in range (0 , len (ops ), 2 ):
5360 ip_map [i ] = ip
5461 opcode , operand = ops [i ], ops [i + 1 ]
55- log ((opcode , operand ))
5662 match opcode :
5763 case 0 :
5864 ins .append (Instruction .SET ("X" , "2" ))
@@ -102,17 +108,44 @@ def combo(operand: int) -> str:
102108 program = Program (ins , output_consumer = lambda s : output .append (s ))
103109 vm = VirtualMachine ()
104110 vm .run_program (program )
105- log (f"{ program .registers = } " )
106- log (f"{ output = } " )
111+ return output
112+
113+ def part_1 (self , input : Input ) -> Output1 :
114+ lines = list (input )
115+ output = self .run_program (lines )
107116 return "," .join (map (str , output ))
108117
109118 def part_2 (self , input : Input ) -> Output2 :
110- return 0
119+ lines = list (input )
120+
121+ def run_with (a : str ) -> list [str ]:
122+ lines [0 ] = "Register A: " + a
123+ return self .run_program (lines )
124+
125+ wanted = lines [4 ][9 :].replace ("," , "" )
126+ log (f"{ wanted = } " )
127+ seen = set (["0" ])
128+ q = deque (["0" ])
129+ while q :
130+ a = q .popleft ()
131+ if "" .join (str (_ ) for _ in run_with (a )) == wanted :
132+ return int (a )
133+ na = int (a ) * 8
134+ for i in range (8 ):
135+ test = str (na + i )
136+ res = "" .join (str (_ ) for _ in run_with (test ))
137+ size = len (res )
138+ if res == wanted [- size :]:
139+ if test not in seen :
140+ seen .add (test )
141+ log (test )
142+ q .append (test )
143+ raise RuntimeError ("unsolvable" )
111144
112145 @aoc_samples (
113146 (
114- ("part_1" , TEST , "4,6,3,5,6,3,5,2,1,0" ),
115- # ("part_2", TEST, "TODO" ),
147+ ("part_1" , TEST1 , "4,6,3,5,6,3,5,2,1,0" ),
148+ ("part_2" , TEST2 , 117440 ),
116149 )
117150 )
118151 def samples (self ) -> None :
0 commit comments