@@ -3,29 +3,27 @@ use common::{solution, Answer};
3
3
solution ! ( "Bridge Repair" , 7 ) ;
4
4
5
5
fn part_a ( input : & str ) -> Answer {
6
- let problem = Problem :: parse ( input) ;
7
- let mut sum = 0 ;
8
-
9
- for case in problem. cases {
10
- if case. is_valid_a ( ) {
11
- sum += case. result ;
12
- }
13
- }
14
-
15
- sum. into ( )
6
+ solve ( input, false ) . into ( )
16
7
}
17
8
18
9
fn part_b ( input : & str ) -> Answer {
19
- let problem = Problem :: parse ( input) ;
20
- let mut sum = 0 ;
10
+ solve ( input, true ) . into ( )
11
+ }
21
12
22
- for case in problem. cases {
23
- if case. is_valid_b_working ( ) {
24
- sum += case. result ;
25
- }
26
- }
13
+ fn solve ( input : & str , part_b : bool ) -> u64 {
14
+ let problem = Problem :: parse ( input) ;
27
15
28
- sum. into ( )
16
+ // For each of the equations, we will add its result value if it is valid.
17
+ // For part a, we check if its valid using `is_valid` with part_b = false,
18
+ // because an equation that is valid for part a is must be valid for part b,
19
+ // we can get a small speedup by only doing the more intense part_b = true
20
+ // check if needed.
21
+ problem
22
+ . cases
23
+ . into_iter ( )
24
+ . filter ( |x| x. is_valid ( false ) || ( part_b && x. is_valid ( true ) ) )
25
+ . map ( |x| x. result )
26
+ . sum :: < u64 > ( )
29
27
}
30
28
31
29
struct Problem {
@@ -66,74 +64,37 @@ impl Problem {
66
64
}
67
65
68
66
impl TestCase {
69
- fn is_valid_a ( & self ) -> bool {
67
+ fn is_valid ( & self , part_b : bool ) -> bool {
70
68
let op_count = self . inputs . len ( ) - 1 ;
71
69
let mut ops = vec ! [ 0 ; op_count] ;
72
70
73
- loop {
71
+ ' outer: loop {
72
+ // Set the result to be the first input value to start. Then update
73
+ // the result for each operation using the previous result and the
74
+ // next number as inputs.
74
75
let mut result = self . inputs [ 0 ] ;
75
76
for ( & op, & input) in ops. iter ( ) . zip ( self . inputs . iter ( ) . skip ( 1 ) ) {
76
77
let op = [ Operations :: Add , Operations :: Multiply , Operations :: Concat ] [ op] ;
77
78
result = op. evaluate ( result, input) ;
78
79
}
79
-
80
- if result == self . result {
81
- return true ;
82
- }
83
-
84
- let mut i = 0 ;
85
- loop {
86
- if i >= op_count {
87
- return false ;
88
- }
89
-
90
- ops[ i] += 1 ;
91
- if ops[ i] > 1 {
92
- ops[ i] = 0 ;
93
- i += 1 ;
94
- continue ;
95
- }
96
-
97
- break ;
98
- }
99
- }
100
- }
101
-
102
- fn is_valid_b_working ( & self ) -> bool {
103
- let op_count = self . inputs . len ( ) - 1 ;
104
- let mut ops = vec ! [ 0 ; op_count] ;
105
-
106
- dbg ! ( & self . inputs) ;
107
- loop {
108
- let mut result = self . inputs [ 0 ] ;
109
- // println!("{ops:?}");
110
- for ( idx, & op) in ops. iter ( ) . enumerate ( ) {
111
- let input = self . inputs [ idx + 1 ] ;
112
- let op = [ Operations :: Add , Operations :: Multiply , Operations :: Concat ] [ op] ;
113
- // println!(" | {op:?} ({result}, {input})");
114
- result = op. evaluate ( result, input) ;
115
- }
116
80
81
+ // If the result we get after applying the operations gets us the
82
+ // expected result, this equation is valid.
117
83
if result == self . result {
118
- // println!(" -> WORKS {result}");
119
84
return true ;
120
85
}
121
86
122
- let mut i = 0 ;
123
- loop {
124
- if i >= op_count {
125
- return false ;
126
- }
127
-
87
+ // Increments the leftmost operation, carrying if it exceeds 1 for
88
+ // part a or 2 for part b.
89
+ for i in 0 ..op_count {
128
90
ops[ i] += 1 ;
129
- if ops[ i] > 2 {
130
- ops[ i] = 0 ;
131
- i += 1 ;
132
- continue ;
91
+ if ops[ i] <= ( 1 + part_b as usize ) {
92
+ continue ' outer;
133
93
}
134
-
135
- break ;
94
+ ops[ i] = 0 ;
136
95
}
96
+
97
+ return false ;
137
98
}
138
99
}
139
100
}
0 commit comments