1
1
package aminetti .adventofcode2024 .day07 ;
2
2
3
- import com .google .common .collect .Iterables ;
4
3
import org .apache .commons .lang3 .StringUtils ;
5
4
import org .slf4j .Logger ;
6
5
import org .slf4j .LoggerFactory ;
7
6
8
7
import java .util .ArrayList ;
9
8
import java .util .Arrays ;
9
+ import java .util .EnumSet ;
10
10
import java .util .List ;
11
11
12
- import static aminetti .adventofcode2024 .day07 .Day07 .Op .MULT ;
12
+ import static aminetti .adventofcode2024 .day07 .Day07 .Op .* ;
13
13
import static com .google .common .collect .Lists .newArrayList ;
14
14
15
15
public class Day07 {
16
16
private static final Logger LOGGER = LoggerFactory .getLogger (Day07 .class );
17
- private List <String > input ;
18
17
private final List <Long > results = new ArrayList <>();
19
18
private final List <List <Long >> components = new ArrayList <>();
20
19
21
20
public Day07 () {
22
21
}
23
22
24
23
public void parseInput (List <String > input ) {
25
- this .input = input ;
26
-
27
24
for (String s : input ) {
28
25
String [] split = s .split (":" );
29
26
results .add (Long .parseLong (split [0 ]));
@@ -33,12 +30,19 @@ public void parseInput(List<String> input) {
33
30
}
34
31
35
32
public long solvePart1 () {
33
+ EnumSet <Op > allowedOps = EnumSet .of (SUM , MULT );
34
+ return countValidEquations (allowedOps );
35
+ }
36
+
37
+ private long countValidEquations (EnumSet <Op > allowedOps ) {
36
38
long sum = 0 ;
37
39
for (int i = 0 ; i < results .size (); i ++) {
38
40
Long result = results .get (i );
39
- long count = countOfCorrectOperators (result , components .get (i ), List .of (), newArrayList ());
40
- LOGGER .debug ("count for {}: {}" , result , count );
41
- if (count > 0 ) {
41
+
42
+ boolean valid = isValid (allowedOps , result , components .get (i ), List .of (), newArrayList ());
43
+ LOGGER .debug ("Is {}: valid? {}" , result , valid );
44
+
45
+ if (valid ) {
42
46
sum += result ;
43
47
}
44
48
}
@@ -48,7 +52,7 @@ public long solvePart1() {
48
52
public enum Op {
49
53
SUM , MULT , CONCAT ;
50
54
51
- public String print () {
55
+ public String toString () {
52
56
return switch (this ) {
53
57
case SUM -> "+" ;
54
58
case MULT -> "*" ;
@@ -57,136 +61,79 @@ public String print() {
57
61
}
58
62
}
59
63
64
+ public long solvePart2 () {
65
+ EnumSet <Op > allowedOps = EnumSet .allOf (Op .class );
66
+ return countValidEquations (allowedOps );
67
+ }
60
68
61
- private long countOfCorrectOperators (long result , List <Long > longs , List <Op > operators , List <Long > components ) {
62
- if (longs .size () == 1 ) {
63
- Long lastEl = Iterables .getOnlyElement (longs );
64
- if (result == lastEl ) {
65
69
66
- String fullOperation = "(" .repeat (operators .size ()) + lastEl ;
70
+ private boolean isValid (final EnumSet <Op > allowedOps , long result , List <Long > lefts , List <Op > operators , List <Long > rights ) {
71
+ if (lefts .isEmpty ()) {
72
+ return false ;
73
+ }
67
74
68
- ArrayList <Op > mutableOps = newArrayList (operators );
69
- ArrayList <Long > mutableComponents = newArrayList (components );
70
- while (!mutableOps .isEmpty ()) {
71
- fullOperation += mutableOps .removeLast ().print () + "" + mutableComponents .removeLast () + ")" ;
72
- }
75
+ ArrayList <Long > nextLeft = newArrayList (lefts );
76
+ Long current = nextLeft .removeLast ();
73
77
74
- LOGGER .debug ("Operation: {}" , fullOperation );
75
- LOGGER .info ("Found correct operators" );
76
- return 1 ;
78
+ if (lefts .size () == 1 ) {
79
+ if (result == current ) {
80
+ String fullOperation = printOperation (operators , rights , current );
81
+ LOGGER .debug ("Found correct operators, operations: {}" , fullOperation );
82
+ return true ;
77
83
}
78
-
79
- return 0 ;
80
-
84
+ return false ;
81
85
}
82
86
83
- if (result <= 0 || longs .isEmpty ()) {
84
- return 0 ;
85
- }
86
-
87
-
88
- ArrayList <Op > opsForSum = newArrayList (operators );
89
- opsForSum .add (Op .SUM );
90
87
91
- ArrayList <Op > opsForMult = newArrayList (operators );
92
- opsForMult .add (MULT );
88
+ ArrayList <Long > nextRights = newArrayList (rights );
89
+ nextRights .add (current );
93
90
94
- ArrayList <Long > next = newArrayList (longs );
95
- Long component = next .removeLast ();
96
-
97
- ArrayList <Long > nextComponents = newArrayList (components );
98
- nextComponents .add (component );
99
-
100
- long sumMult = 0 ;
101
- if (result % component == 0 ) {
102
- sumMult += countOfCorrectOperators (result / component , next , opsForMult , nextComponents );
103
- }
104
- return sumMult
105
- + countOfCorrectOperators (result - component , next , opsForSum , nextComponents );
106
- }
107
-
108
- public long solvePart2 () {
109
- long sum = 0 ;
110
- for (int i = 0 ; i < results .size (); i ++) {
111
- Long result = results .get (i );
112
-
113
- LOGGER .debug ("Checking {}" , result );
114
- long count = countOfCorrectOperatorsWithConcat (result , components .get (i ), List .of (), newArrayList ());
115
- LOGGER .debug ("count for {}: {}" , result , count );
116
- if (count > 0 ) {
117
- sum += result ;
91
+ if (allowedOps .contains (MULT ) && result % current == 0 ) { // divisions are the fastest to decrease a value
92
+ ArrayList <Op > opsForMult = newArrayList (operators );
93
+ opsForMult .add (MULT );
94
+ if (isValid (allowedOps , result / current , nextLeft , opsForMult , nextRights )) {
95
+ return true ;
118
96
}
119
97
}
120
- return sum ;
121
- }
122
-
123
-
124
- private long countOfCorrectOperatorsWithConcat (long result , List <Long > longs , List <Op > operators , List <Long > components ) {
125
- if (longs .size () == 1 ) {
126
- Long lastEl = Iterables .getOnlyElement (longs );
127
- if (result == lastEl ) {
128
-
129
- String fullOperation = "(" .repeat (operators .size ()) + lastEl ;
130
98
131
- ArrayList <Op > mutableOps = newArrayList (operators );
132
- ArrayList <Long > mutableComponents = newArrayList (components );
133
- while (!mutableOps .isEmpty ()) {
134
- fullOperation += mutableOps .removeLast ().print () + "" + mutableComponents .removeLast () + ")" ;
135
- }
99
+ String stringResult = "" + result ;
100
+ String stringComponent = "" + current ;
101
+ if (allowedOps .contains (CONCAT ) && stringResult .length () > stringComponent .length () && stringResult .endsWith (stringComponent )) {
102
+ // split a number (~divide by 10^log10(current) ) could be slower than divisions but faster than subtractions to decrease a value
103
+ ArrayList <Op > opsForConcat = newArrayList (operators );
104
+ opsForConcat .add (CONCAT );
136
105
137
- LOGGER . debug ( "Operation: {}" , fullOperation );
138
- LOGGER . info ( "Found correct operators" );
139
- return 1 ;
106
+ long expectedResult = Long . parseLong ( stringResult . substring ( 0 , stringResult . length () - stringComponent . length ()) );
107
+ if ( isValid ( allowedOps , expectedResult , nextLeft , opsForConcat , nextRights )) {
108
+ return true ;
140
109
}
141
-
142
- return 0 ;
143
-
144
110
}
145
111
146
- if (result <= 0 || longs .isEmpty ()) {
147
- return 0 ;
112
+ if (allowedOps .contains (SUM ) && result - current > 0 ) {
113
+ ArrayList <Op > opsForSum = newArrayList (operators );
114
+ opsForSum .add (SUM );
115
+ if (isValid (allowedOps , result - current , nextLeft , opsForSum , nextRights )) {
116
+ return true ;
117
+ }
148
118
}
149
119
150
120
151
- ArrayList <Op > opsForSum = newArrayList (operators );
152
- opsForSum .add (Op .SUM );
153
121
122
+ return false ;
123
+ }
154
124
125
+ private static String printOperation (List <Op > operators , List <Long > components , Long lastEl ) {
126
+ StringBuilder fullOperation = new StringBuilder ("(" .repeat (operators .size ()) + lastEl );
155
127
156
- ArrayList <Long > next = newArrayList (longs );
157
- Long component = next .removeLast ();
158
-
159
- ArrayList <Long > nextComponents = newArrayList (components );
160
- nextComponents .add (component );
161
-
162
- long sumConcat = 0 ;
163
- String stringResult = "" + result ;
164
- String stringComponent = "" + component ;
165
-
166
- LOGGER .info ("Result: {} - longs: {}" , result , longs );
167
- LOGGER .info ("Result: {} - stringComponent: {}" , stringResult , stringComponent );
168
-
169
- if (stringResult .length () > stringComponent .length () && stringResult .endsWith (stringComponent )) {
170
- LOGGER .info ("Trailing matches: Result: {} - stringComponent: {}" , stringResult , stringComponent );
171
-
172
- ArrayList <Op > opsForConcat = newArrayList (operators );
173
- opsForConcat .add (Op .CONCAT );
128
+ ArrayList <Op > mutableOps = newArrayList (operators );
129
+ ArrayList <Long > mutableComponents = newArrayList (components );
174
130
175
- long expectedResult = Long .parseLong (stringResult .substring (0 , stringResult .length () - stringComponent .length ()));
176
- LOGGER .info ("expectedResult: {}" , expectedResult );
177
- sumConcat += countOfCorrectOperatorsWithConcat (
178
- expectedResult ,
179
- next , opsForConcat , nextComponents );
131
+ while (!mutableOps .isEmpty ()) {
132
+ fullOperation .append (mutableOps .removeLast ())
133
+ .append (mutableComponents .removeLast ()).append (")" );
180
134
}
181
135
182
- long sumMult = 0 ;
183
- if (result % component == 0 ) {
184
- ArrayList <Op > opsForMult = newArrayList (operators );
185
- opsForMult .add (MULT );
186
- sumMult += countOfCorrectOperatorsWithConcat (result / component , next , opsForMult , nextComponents );
187
- }
188
- return sumMult + sumConcat
189
- + countOfCorrectOperatorsWithConcat (result - component , next , opsForSum , nextComponents );
136
+ return fullOperation .toString ();
190
137
}
191
138
192
139
}
0 commit comments