@@ -48,16 +48,16 @@ def get_combo_value(self, operand: int) -> int:
4848 """
4949 if 0 <= operand <= 3 :
5050 return operand
51-
51+
5252 elif operand == 4 :
5353 return self .registers ["A" ]
54-
54+
5555 elif operand == 5 :
5656 return self .registers ["B" ]
57-
57+
5858 elif operand == 6 :
5959 return self .registers ["C" ]
60-
60+
6161 else :
6262 raise ValueError (f"Invalid combo operand: { operand } " )
6363
@@ -100,7 +100,7 @@ def execute_instruction(self, program: List[int]) -> bool:
100100 if self .registers ["A" ] != 0 :
101101 self .instruction_pointer = operand
102102 return True
103-
103+
104104 elif opcode == 4 : # bxc
105105 self .registers ["B" ] ^= self .registers ["C" ]
106106
@@ -116,32 +116,41 @@ def execute_instruction(self, program: List[int]) -> bool:
116116 self .instruction_pointer += 2
117117 return True
118118
119- def run (self , program : List [int ]) -> str :
119+ def run (self , program : List [int ]) -> List [ int ] :
120120 """Run the entire program until completion.
121121
122122 Args:
123123 program (List[int]): List of integers representing the program instructions
124124
125125 Returns:
126- str: Comma-separated string of output values generated during execution
126+ List[int]: List of output values generated during execution
127127 """
128+ self .output = [] # Reset output before running
128129 while self .execute_instruction (program ):
129130 pass
130131
131- return "," . join ( map ( str , self .output ))
132+ return self .output
132133
133- def check_output (self , program : List [int ]) -> bool :
134+ def check_output (self , program : List [int ], partial : bool = False ) -> bool :
134135 """Check if the program's output matches its own instructions.
135136
136137 Args:
137138 program (List[int]): List of integers representing the program instructions
139+ partial (bool, optional): If True, allow checking partial output matches.
140+ Defaults to False.
138141
139142 Returns:
140- bool: True if program output exactly matches the input program, False otherwise
143+ bool: True if program output exactly matches the input program
144+ (or matches partially if partial=True), False otherwise
141145 """
142- output_str = self .run (program )
143- output_numbers = [int (x ) for x in output_str .split ("," )]
144- return output_numbers == program
146+ output = self .run (program )
147+ if len (output ) > len (program ):
148+ return False
149+
150+ if partial :
151+ return output == program [: len (output )]
152+
153+ return output == program
145154
146155
147156class Solution (SolutionBase ):
@@ -194,25 +203,42 @@ def part1(self, data: List[str]) -> str:
194203 """
195204 reg_a , reg_b , reg_c , program = self .parse_data (data )
196205 computer = ThreeBitComputer (reg_a , reg_b , reg_c )
197- return computer .run (program )
206+ return "," . join ( map ( str , computer .run (program )) )
198207
199208 def part2 (self , data : List [str ]) -> int :
200209 """Find lowest positive value for register A that makes program output itself.
201210
211+ Uses mathematical patterns based on powers of 8 to efficiently find the solution.
212+ Each digit in the output corresponds to a power of 8, allowing us to adjust the
213+ input value A systematically rather than trying every possibility.
214+
202215 Args:
203216 data (List[str]): Input lines containing register values and program
204217
205218 Returns:
206219 int: Lowest positive value for register A that causes program to output
207220 a copy of its own instructions
221+
222+ Raises:
223+ ValueError: If the program generates output longer than itself
208224 """
209225 _ , reg_b , reg_c , program = self .parse_data (data )
210226
211- # Start from 1 as we need lowest positive value
212- a = 1
227+ # Calculate initial value based on program length and powers of 8
228+ a = sum (7 * 8 ** i for i in range (len (program ) - 1 )) + 1
229+
213230 while True :
214231 computer = ThreeBitComputer (a , reg_b , reg_c )
215- if computer .check_output (program ):
232+ output = computer .run (program )
233+
234+ if len (output ) > len (program ):
235+ raise ValueError ("Output longer than program" )
236+
237+ if output == program :
216238 return a
217239
218- a += 1
240+ # Find position of first mismatch and adjust A accordingly
241+ for i in range (len (output ) - 1 , - 1 , - 1 ):
242+ if output [i ] != program [i ]:
243+ a += 8 ** i # Adjust A by power of 8 at mismatch position
244+ break
0 commit comments