Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 81f7711

Browse filesBrowse files
committed
AoC 2024 Day 24 - java - cleanup
1 parent 879c2aa commit 81f7711
Copy full SHA for 81f7711

File tree

Expand file treeCollapse file tree

1 file changed

+73
-143
lines changed
Filter options
Expand file treeCollapse file tree

1 file changed

+73
-143
lines changed

‎src/main/java/AoC2024_24.java

Copy file name to clipboard
+73-143Lines changed: 73 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
1+
import static com.github.pareronia.aoc.IntegerSequence.Range.rangeClosed;
2+
import static com.github.pareronia.aoc.StringOps.splitOnce;
13
import static java.util.Objects.requireNonNull;
24
import static java.util.function.Function.identity;
35
import static java.util.stream.Collectors.joining;
4-
import static java.util.stream.Collectors.toList;
56
import static java.util.stream.Collectors.toMap;
67

78
import java.util.Collection;
8-
import java.util.HashSet;
99
import java.util.List;
1010
import java.util.Map;
11-
import java.util.Optional;
1211
import java.util.Set;
12+
import java.util.function.BiPredicate;
13+
import java.util.function.Predicate;
1314

14-
import com.github.pareronia.aoc.StringOps;
1515
import com.github.pareronia.aoc.StringOps.StringSplit;
1616
import com.github.pareronia.aoc.StringUtils;
1717
import com.github.pareronia.aoc.solution.Sample;
1818
import com.github.pareronia.aoc.solution.Samples;
1919
import com.github.pareronia.aoc.solution.SolutionBase;
2020

21-
public class AoC2024_24 extends SolutionBase<List<AoC2024_24.Gate>, Long, String> {
21+
public class AoC2024_24 extends SolutionBase<AoC2024_24.Circuit, Long, String> {
2222

2323
private AoC2024_24(final boolean debug) {
2424
super(debug);
@@ -33,67 +33,55 @@ public static final AoC2024_24 createDebug() {
3333
}
3434

3535
@Override
36-
protected List<Gate> parseInput(final List<String> inputs) {
37-
return inputs.stream().filter(s -> !s.isBlank()).map(Gate::fromInput).collect(toList());
36+
protected Circuit parseInput(final List<String> inputs) {
37+
return Circuit.fromInput(inputs);
3838
}
3939

40-
int part1(final List<Gate> inputs, final String wire) {
41-
final Circuit circuit = Circuit.of(inputs);
42-
return circuit.getValue(wire);
43-
}
44-
4540
@Override
46-
public Long solvePart1(final List<Gate> inputs) {
47-
String ans = "";
48-
for (int i = 0; i <= 45; i++) {
49-
try {
50-
ans = part1(inputs, String.format("z%02d", i)) + ans;
51-
} catch (final AssertionError e) {
52-
}
53-
}
54-
return Long.parseLong(ans, 2);
41+
public Long solvePart1(final Circuit circuit) {
42+
final int maxZ = circuit.getGates().stream()
43+
.filter(gate -> gate.getName().startsWith("z"))
44+
.map(gate -> gate.getName().substring(1))
45+
.mapToInt(Integer::parseInt)
46+
.max().getAsInt();
47+
return rangeClosed(maxZ, 0, -1).intStream()
48+
.mapToLong(i -> ((1L << i)
49+
* circuit.getValue("z%02d".formatted(i))))
50+
.sum();
5551
}
5652

5753
@Override
58-
public String solvePart2(final List<Gate> inputs) {
59-
final List<Gate> gates = Circuit.of(inputs).getGates().stream().filter(gate -> gate.op != AoC2024_24.Gate.Op.SET).toList();
60-
final Set<String> swapped = new HashSet<>();
61-
for (final Gate gate : gates) {
62-
if (gate.op == AoC2024_24.Gate.Op.SET) {
63-
continue;
64-
}
65-
if (gate.name.startsWith("z")
66-
&& gate.op != AoC2024_24.Gate.Op.XOR
67-
&& !gate.name.equals("z45")) {
68-
swapped.add(gate.name);
69-
}
70-
if (gate.op == AoC2024_24.Gate.Op.XOR
54+
public String solvePart2(final Circuit circuit) {
55+
final Predicate<Gate> outputsToZExceptFirstOneAndNotXOR
56+
= gate -> (gate.name.startsWith("z")
57+
&& gate.op != Gate.Op.XOR
58+
&& !gate.name.equals("z45"));
59+
final Predicate<Gate> isXORNotConnectedToXorYorZ
60+
= gate -> gate.op == Gate.Op.XOR
7161
&& Set.of(gate.name, gate.in1, gate.in2).stream()
72-
.noneMatch(n -> n.startsWith("x")
73-
|| n.startsWith("y")
74-
|| n.startsWith("z"))) {
75-
swapped.add(gate.name);
76-
}
77-
if (gate.op == AoC2024_24.Gate.Op.AND
78-
&& !(gate.in1.equals("x00") || gate.in2.equals("x00"))) {
79-
for (final Gate other : gates) {
80-
if (other.op != AoC2024_24.Gate.Op.OR
81-
&& (Set.of(other.in1, other.in2).contains(gate.name))) {
82-
swapped.add(gate.name);
83-
}
84-
}
85-
}
86-
if (gate.op == AoC2024_24.Gate.Op.XOR) {
87-
for (final Gate other : gates) {
88-
if (other.op == AoC2024_24.Gate.Op.OR
89-
&& (Set.of(other.in1, other.in2).contains(gate.name))) {
90-
swapped.add(gate.name);
91-
}
92-
}
93-
}
94-
}
95-
log(swapped);
96-
return swapped.stream().sorted().collect(joining(","));
62+
.noneMatch(n -> n.startsWith("x")
63+
|| n.startsWith("y")
64+
|| n.startsWith("z"));
65+
final BiPredicate<Gate, List<Gate>> isANDExceptLastWithAnOutputNotToOR
66+
= (gate, others) -> (gate.op == Gate.Op.AND
67+
&& !(gate.in1.equals("x00") || gate.in2.equals("x00"))
68+
&& others.stream().anyMatch(other -> other.op != Gate.Op.OR
69+
&& (Set.of(other.in1, other.in2).contains(gate.name))));
70+
final BiPredicate<Gate, List<Gate>> isXORWithAnOutputToOR
71+
= (gate, others) -> (gate.op == Gate.Op.XOR
72+
&& others.stream().anyMatch(other -> other.op == Gate.Op.OR
73+
&& (Set.of(other.in1, other.in2).contains(gate.name))));
74+
final List<Gate> gates = circuit.getGates().stream()
75+
.filter(gate -> gate.op != Gate.Op.SET)
76+
.toList();
77+
return gates.stream()
78+
.filter(gate -> outputsToZExceptFirstOneAndNotXOR.test(gate)
79+
|| isXORNotConnectedToXorYorZ.test(gate)
80+
|| isANDExceptLastWithAnOutputNotToOR.test(gate, gates)
81+
|| isXORWithAnOutputToOR.test(gate, gates))
82+
.map(Gate::getName)
83+
.sorted()
84+
.collect(joining(","));
9785
}
9886

9987
@Override
@@ -170,7 +158,7 @@ public static void main(final String[] args) throws Exception {
170158
tnw OR pbm -> gnj
171159
""";
172160

173-
static final class Gate implements Cloneable {
161+
static final class Gate {
174162

175163
enum Op { SET, AND, OR, XOR }
176164

@@ -197,38 +185,24 @@ protected Gate(
197185

198186
public static Gate fromInput(final String input) {
199187
if (input.contains(": ")) {
200-
final StringSplit splits = StringOps.splitOnce(input, ": ");
188+
final StringSplit splits = splitOnce(input, ": ");
201189
return Gate.set(splits.left(), splits.right());
202190
}
203-
final String[] splits = input.split(" -> ");
204-
if (splits[0].contains("AND")) {
205-
final String[] andSplits = splits[0].split(" AND ");
206-
return Gate.and(splits[1], andSplits[0], andSplits[1]);
207-
} else if (splits[0].contains("XOR")) {
208-
final String in = splits[0].substring(" XOR ".length());
209-
final String[] xorSplits = splits[0].split(" XOR ");
210-
return Gate.xor(splits[1], xorSplits[0], xorSplits[1]);
211-
} else if (splits[0].contains("OR") && !splits[0].contains("XOR")) {
212-
final String[] orSplits = splits[0].split(" OR ");
213-
return Gate.or(splits[1], orSplits[0], orSplits[1]);
191+
final StringSplit splits = splitOnce(input, " -> ");
192+
if (splits.left().contains("AND")) {
193+
final StringSplit andSplits = splitOnce(splits.left(), " AND ");
194+
return Gate.and(splits.right(), andSplits.left(), andSplits.right());
195+
} else if (splits.left().contains("XOR")) {
196+
final StringSplit xorSplits = splitOnce(splits.left(), " XOR ");
197+
return Gate.xor(splits.right(), xorSplits.left(), xorSplits.right());
198+
} else if (splits.left().contains("OR") && !splits.left().contains("XOR")) {
199+
final StringSplit orSplits = splitOnce(splits.left(), " OR ");
200+
return Gate.or(splits.right(), orSplits.left(), orSplits.right());
214201
} else {
215202
throw new IllegalArgumentException();
216203
}
217204
}
218205

219-
@Override
220-
protected Gate clone() throws CloneNotSupportedException {
221-
return new Gate(this.name, this.in1, this.in2, this.op, this.arg);
222-
}
223-
224-
public static Gate cloneGate(final Gate gate) {
225-
try {
226-
return gate.clone();
227-
} catch (final CloneNotSupportedException e) {
228-
throw new RuntimeException(e);
229-
}
230-
}
231-
232206
public static Gate xor(final String name, final String in) {
233207
return new Gate(name, in, null, Op.XOR, null);
234208
}
@@ -259,20 +233,10 @@ public Integer getResult() {
259233

260234
public Integer updateResult(final Integer in1, final Integer in2) {
261235
switch (this.op) {
262-
case SET:
263-
this.result = in1;
264-
break;
265-
case AND:
266-
this.result = in1 & in2;
267-
break;
268-
case XOR:
269-
this.result = in1 ^ in2;
270-
break;
271-
case OR:
272-
this.result = in1 | in2;
273-
break;
274-
default:
275-
throw new IllegalStateException();
236+
case SET -> this.result = in1;
237+
case AND -> this.result = in1 & in2;
238+
case XOR -> this.result = in1 ^ in2;
239+
case OR -> this.result = in1 | in2;
276240
}
277241
return this.result;
278242
}
@@ -281,35 +245,22 @@ public Integer updateResult(final Integer in1, final Integer in2) {
281245
public String toString() {
282246
final StringBuilder sb = new StringBuilder();
283247
switch (this.op) {
284-
case SET:
285-
sb.append(this.in1);
286-
break;
287-
case AND:
288-
sb.append(this.in1).append(" AND ").append(this.in2);
289-
break;
290-
case OR:
291-
sb.append(this.in1).append(" OR ").append(this.in2);
292-
break;
293-
case XOR:
294-
sb.append(this.in1).append(" XOR ").append(this.in2);
295-
break;
296-
default:
297-
throw new IllegalStateException();
248+
case SET -> sb.append(this.in1);
249+
case AND -> sb.append(this.in1).append(" AND ").append(this.in2);
250+
case OR -> sb.append(this.in1).append(" OR ").append(this.in2);
251+
case XOR -> sb.append(this.in1).append(" XOR ").append(this.in2);
298252
}
299253
return sb.toString();
300254
}
301255
}
302256

303-
private static final class Circuit {
304-
private final Map<String, Gate> gates;
257+
record Circuit(Map<String, Gate> gates) {
305258

306-
protected Circuit(final Map<String, AoC2024_24.Gate> gates) {
307-
this.gates = gates;
308-
}
309-
310-
public static Circuit of(final Collection<Gate> gates) {
311-
return new Circuit(requireNonNull(gates).stream()
312-
.collect(toMap(Gate::getName, identity())));
259+
public static Circuit fromInput(final List<String> inputs) {
260+
return new Circuit(inputs.stream()
261+
.filter(s -> !s.isBlank())
262+
.map(Gate::fromInput)
263+
.collect(toMap(Gate::getName, identity())));
313264
}
314265

315266
public Collection<Gate> getGates() {
@@ -320,20 +271,6 @@ public Gate getGate(final String name) {
320271
return this.gates.get(requireNonNull(name));
321272
}
322273

323-
public void setGate(final String name, final Gate gate) {
324-
this.gates.put(requireNonNull(name), requireNonNull(gate));
325-
}
326-
327-
public Optional<Gate> getGateIn1(final String name) {
328-
final Gate gate = this.getGate(name);
329-
return Optional.ofNullable(gate.in1).map(this::getGate);
330-
}
331-
332-
public Optional<Gate> getGateIn2(final String name) {
333-
final Gate gate = this.getGate(name);
334-
return Optional.ofNullable(gate.in2).map(this::getGate);
335-
}
336-
337274
public int getValue(final String name) {
338275
assert name != null && !name.isEmpty(): "name is empty";
339276
if (StringUtils.isNumeric(name)) {
@@ -349,12 +286,5 @@ public int getValue(final String name) {
349286
final Integer in2 = gate.in2 != null ? getValue(gate.in2) : null;
350287
return gate.updateResult(in1, in2);
351288
}
352-
353-
@Override
354-
public String toString() {
355-
final StringBuilder builder = new StringBuilder();
356-
builder.append("Circuit [gates=").append(gates).append("]");
357-
return builder.toString();
358-
}
359289
}
360290
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.