1
- use heapless:: Vec as HeaplessVec ;
2
1
use rayon:: iter:: { IntoParallelRefIterator , ParallelIterator } ;
3
2
advent_of_code:: solution!( 7 ) ;
4
3
@@ -25,58 +24,48 @@ impl EquationData {
25
24
26
25
#[ inline]
27
26
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 ) ] ;
40
29
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 {
44
34
return true ;
45
35
}
46
36
continue ;
47
37
}
48
38
49
- let next_idx = ops. len ( ) + 1 ;
50
- let next_value = self . values [ next_idx] ;
39
+ let n = self . values [ idx] ;
51
40
52
- // Try each available operation
53
41
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
+ }
57
53
Op :: Concat => {
58
54
let mut digit_count = 0 ;
59
- let mut n = next_value ;
60
- while n > 0 {
55
+ let mut temp = n ;
56
+ while temp > 0 {
61
57
digit_count += 1 ;
62
- n /= 10 ;
58
+ temp /= 10 ;
63
59
}
64
- current_value * 10_u64 . pow ( digit_count) + next_value
65
- }
66
- } ;
60
+ let divisor = 10_u64 . pow ( digit_count) ;
67
61
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
+ }
71
66
}
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 ( ) ;
77
67
}
78
68
}
79
-
80
69
false
81
70
}
82
71
}
0 commit comments