1- use heapless:: Vec as HeaplessVec ;
21use rayon:: iter:: { IntoParallelRefIterator , ParallelIterator } ;
32advent_of_code:: solution!( 7 ) ;
43
@@ -25,58 +24,48 @@ impl EquationData {
2524
2625 #[ inline]
2726 fn has_valid_ops_combination ( & self , available_ops : & [ Op ] ) -> bool {
28- let needed_ops = self . values . len ( ) - 1 ;
29- if needed_ops == 0 {
30- return self . values [ 0 ] == self . test_value ;
31- }
32-
33- const OPS_SIZE : usize = 16 ;
34- const STACK_SIZE : usize = 32 ;
35-
36- let mut stack = HeaplessVec :: < _ , STACK_SIZE > :: new ( ) ;
37- stack
38- . push ( ( self . values [ 0 ] , HeaplessVec :: < _ , OPS_SIZE > :: new ( ) ) )
39- . unwrap ( ) ;
27+ // Stack will store (current_target, remaining_numbers_index);
28+ let mut stack = vec ! [ ( self . test_value, self . values. len( ) - 1 ) ] ;
4029
41- while let Some ( ( current_value, mut ops) ) = stack. pop ( ) {
42- if ops. len ( ) == needed_ops {
43- if current_value == self . test_value {
30+ while let Some ( ( current_target, idx) ) = stack. pop ( ) {
31+ // Base case - if we're at the first number
32+ if idx == 0 {
33+ if self . values [ 0 ] == current_target {
4434 return true ;
4535 }
4636 continue ;
4737 }
4838
49- let next_idx = ops. len ( ) + 1 ;
50- let next_value = self . values [ next_idx] ;
39+ let n = self . values [ idx] ;
5140
52- // Try each available operation
5341 for & op in available_ops {
54- let new_value = match op {
55- Op :: Add => current_value + next_value,
56- Op :: Mul => current_value * next_value,
42+ match op {
43+ Op :: Add => {
44+ if current_target >= n {
45+ stack. push ( ( current_target - n, idx - 1 ) ) ;
46+ }
47+ }
48+ Op :: Mul => {
49+ if current_target % n == 0 {
50+ stack. push ( ( current_target / n, idx - 1 ) ) ;
51+ }
52+ }
5753 Op :: Concat => {
5854 let mut digit_count = 0 ;
59- let mut n = next_value ;
60- while n > 0 {
55+ let mut temp = n ;
56+ while temp > 0 {
6157 digit_count += 1 ;
62- n /= 10 ;
58+ temp /= 10 ;
6359 }
64- current_value * 10_u64 . pow ( digit_count) + next_value
65- }
66- } ;
60+ let divisor = 10_u64 . pow ( digit_count) ;
6761
68- // Skip if we've already exceeded the target
69- if new_value > self . test_value {
70- continue ;
62+ if current_target % divisor == n {
63+ stack. push ( ( current_target / divisor, idx - 1 ) ) ;
64+ }
65+ }
7166 }
72-
73- // Create new ops vector and push to stack
74- ops. push ( op) . unwrap ( ) ;
75- stack. push ( ( new_value, ops. clone ( ) ) ) . unwrap ( ) ;
76- ops. pop ( ) ;
7767 }
7868 }
79-
8069 false
8170 }
8271}
0 commit comments