Skip to content

Commit 392f19a

Browse files
day07 for AoC 2024 (part 2) refactor to use a common logic for part 1 and part 2; fail-fast with a guard for the subtractions too; prioritize the multiplication over concat and concat over additions because they of their natual magnitude
Took 36 minutes
1 parent c0f5343 commit 392f19a

File tree

1 file changed

+61
-114
lines changed
  • src/main/java/aminetti/adventofcode2024/day07

1 file changed

+61
-114
lines changed
Lines changed: 61 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,26 @@
11
package aminetti.adventofcode2024.day07;
22

3-
import com.google.common.collect.Iterables;
43
import org.apache.commons.lang3.StringUtils;
54
import org.slf4j.Logger;
65
import org.slf4j.LoggerFactory;
76

87
import java.util.ArrayList;
98
import java.util.Arrays;
9+
import java.util.EnumSet;
1010
import java.util.List;
1111

12-
import static aminetti.adventofcode2024.day07.Day07.Op.MULT;
12+
import static aminetti.adventofcode2024.day07.Day07.Op.*;
1313
import static com.google.common.collect.Lists.newArrayList;
1414

1515
public class Day07 {
1616
private static final Logger LOGGER = LoggerFactory.getLogger(Day07.class);
17-
private List<String> input;
1817
private final List<Long> results = new ArrayList<>();
1918
private final List<List<Long>> components = new ArrayList<>();
2019

2120
public Day07() {
2221
}
2322

2423
public void parseInput(List<String> input) {
25-
this.input = input;
26-
2724
for (String s : input) {
2825
String[] split = s.split(":");
2926
results.add(Long.parseLong(split[0]));
@@ -33,12 +30,19 @@ public void parseInput(List<String> input) {
3330
}
3431

3532
public long solvePart1() {
33+
EnumSet<Op> allowedOps = EnumSet.of(SUM, MULT);
34+
return countValidEquations(allowedOps);
35+
}
36+
37+
private long countValidEquations(EnumSet<Op> allowedOps) {
3638
long sum = 0;
3739
for (int i = 0; i < results.size(); i++) {
3840
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) {
4246
sum += result;
4347
}
4448
}
@@ -48,7 +52,7 @@ public long solvePart1() {
4852
public enum Op {
4953
SUM, MULT, CONCAT;
5054

51-
public String print() {
55+
public String toString() {
5256
return switch (this) {
5357
case SUM -> "+";
5458
case MULT -> "*";
@@ -57,136 +61,79 @@ public String print() {
5761
}
5862
}
5963

64+
public long solvePart2() {
65+
EnumSet<Op> allowedOps = EnumSet.allOf(Op.class);
66+
return countValidEquations(allowedOps);
67+
}
6068

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) {
6569

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+
}
6774

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();
7377

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;
7783
}
78-
79-
return 0;
80-
84+
return false;
8185
}
8286

83-
if (result <= 0 || longs.isEmpty()) {
84-
return 0;
85-
}
86-
87-
88-
ArrayList<Op> opsForSum = newArrayList(operators);
89-
opsForSum.add(Op.SUM);
9087

91-
ArrayList<Op> opsForMult = newArrayList(operators);
92-
opsForMult.add(MULT);
88+
ArrayList<Long> nextRights = newArrayList(rights);
89+
nextRights.add(current);
9390

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;
11896
}
11997
}
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;
13098

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);
136105

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;
140109
}
141-
142-
return 0;
143-
144110
}
145111

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+
}
148118
}
149119

150120

151-
ArrayList<Op> opsForSum = newArrayList(operators);
152-
opsForSum.add(Op.SUM);
153121

122+
return false;
123+
}
154124

125+
private static String printOperation(List<Op> operators, List<Long> components, Long lastEl) {
126+
StringBuilder fullOperation = new StringBuilder("(".repeat(operators.size()) + lastEl);
155127

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);
174130

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(")");
180134
}
181135

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();
190137
}
191138

192139
}

0 commit comments

Comments
 (0)