-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAoC2024_07.java
More file actions
124 lines (110 loc) Β· 4.13 KB
/
AoC2024_07.java
File metadata and controls
124 lines (110 loc) Β· 4.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import com.github.pareronia.aoc.StringOps;
import com.github.pareronia.aoc.StringOps.StringSplit;
import com.github.pareronia.aoc.solution.Sample;
import com.github.pareronia.aoc.solution.Samples;
import com.github.pareronia.aoc.solution.SolutionBase;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
@SuppressWarnings({"PMD.ClassNamingConventions", "PMD.NoPackage"})
public final class AoC2024_07 extends SolutionBase<List<AoC2024_07.Equation>, Long, Long> {
private AoC2024_07(final boolean debug) {
super(debug);
}
public static AoC2024_07 create() {
return new AoC2024_07(false);
}
public static AoC2024_07 createDebug() {
return new AoC2024_07(true);
}
@Override
protected List<Equation> parseInput(final List<String> inputs) {
final List<Equation> equations = new ArrayList<>();
for (final String line : inputs) {
final StringSplit splits = StringOps.splitOnce(line, ": ");
final Long sol = Long.valueOf(splits.left());
final List<Long> terms =
Arrays.stream(splits.right().split(" ")).map(Long::valueOf).toList();
equations.add(new Equation(sol, terms));
}
return equations;
}
@SuppressWarnings({
"PMD.OnlyOneReturn",
"PMD.CognitiveComplexity",
"PMD.AvoidLiteralsInIfCondition",
"PMD.AvoidDeeplyNestedIfStmts",
"PMD.UseUtilityClass"
})
private long solve(final List<Equation> equations, final Set<Op> ops) {
final class Test {
static boolean canObtain(final long sol, final List<Long> terms, final Set<Op> ops) {
if (terms.size() == 1) {
return sol == terms.get(0);
}
if (ops.contains(Op.ADD)
&& sol % terms.getLast() == 0
&& canObtain(
sol / terms.getLast(), terms.subList(0, terms.size() - 1), ops)) {
return true;
}
if (ops.contains(Op.MULTIPLY)
&& sol > terms.getLast()
&& canObtain(
sol - terms.getLast(), terms.subList(0, terms.size() - 1), ops)) {
return true;
}
if (ops.contains(Op.CONCATENATE)) {
final String sSol = String.valueOf(sol);
final String sLast = String.valueOf(terms.getLast());
if (sSol.length() > sLast.length() && sSol.endsWith(sLast)) {
final String newSol = sSol.substring(0, sSol.length() - sLast.length());
if (canObtain(
Long.parseLong(newSol), terms.subList(0, terms.size() - 1), ops)) {
return true;
}
}
}
return false;
}
}
return equations.stream()
.filter(eq -> Test.canObtain(eq.sol, eq.terms, ops))
.mapToLong(Equation::sol)
.sum();
}
@Override
public Long solvePart1(final List<Equation> equations) {
return solve(equations, Set.of(Op.ADD, Op.MULTIPLY));
}
@Override
public Long solvePart2(final List<Equation> equations) {
return solve(equations, Set.of(Op.ADD, Op.MULTIPLY, Op.CONCATENATE));
}
@Samples({
@Sample(method = "part1", input = TEST, expected = "3749"),
@Sample(method = "part2", input = TEST, expected = "11387"),
})
public static void main(final String[] args) throws Exception {
create().run();
}
private static final String TEST =
"""
190: 10 19
3267: 81 40 27
83: 17 5
156: 15 6
7290: 6 8 6 15
161011: 16 10 13
192: 17 8 14
21037: 9 7 18 13
292: 11 6 16 20
""";
private enum Op {
ADD,
MULTIPLY,
CONCATENATE;
}
record Equation(Long sol, List<Long> terms) {}
}