Skip to content

Commit afd3588

Browse files
committed
Day 21
1 parent bc07f57 commit afd3588

File tree

2 files changed

+338
-0
lines changed

2 files changed

+338
-0
lines changed

src/test/java/com/macasaet/Day21.java

Lines changed: 323 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,323 @@
1+
package com.macasaet;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import java.util.Collections;
6+
import java.util.HashMap;
7+
import java.util.Map;
8+
import java.util.stream.StreamSupport;
9+
10+
/**
11+
* --- Day 21: Monkey Math ---
12+
* <a href="https://adventofcode.com/2022/day/21">https://adventofcode.com/2022/day/21</a>
13+
*/
14+
public class Day21 {
15+
16+
public record Monkey(String name, Job job) {
17+
public long yell(final Map<String, Monkey> monkeys, final Map<String, Long> results) {
18+
return job().yell(monkeys, results);
19+
}
20+
21+
public Simplification simplify(final Map<String, Monkey> monkeys, final Map<String, Long> results) {
22+
return job().simplify(monkeys, results);
23+
}
24+
25+
public static Monkey parse(final String line) {
26+
final var components = line.split(": ");
27+
final var name = components[0].trim();
28+
final var job = Job.parse(components[1].trim());
29+
return new Monkey(name, job);
30+
}
31+
}
32+
33+
public interface Simplification {
34+
Simplification simplify();
35+
}
36+
37+
record Expression(Simplification x, Operation operation, Simplification y) implements Simplification {
38+
39+
public Simplification simplify() {
40+
final var simpleX = x().simplify();
41+
final var simpleY = y().simplify();
42+
if (!x().equals(simpleX) || !y().equals(simpleY)) {
43+
return new Expression(simpleX, operation(), simpleY);
44+
} else if (x() instanceof Value && y() instanceof Value) {
45+
return new Value(operation().operate(((Value) x).value(), ((Value) y).value()));
46+
} else if (operation() == Operation.IS_EQUAL) {
47+
if (x() instanceof final Value constant && y() instanceof final Expression expression) {
48+
// e.g. 5=2/x or 5=x/2
49+
final var inverse = expression.operation().inverse();
50+
if (expression.x() instanceof Value) {
51+
// e.g. 5=2/x
52+
if (expression.operation.isSymmetric()) {
53+
// e.g. 2=5x -> 10=x
54+
final var lValue = new Expression(constant, inverse, expression.x()).simplify();
55+
return new Expression(lValue, Operation.IS_EQUAL, expression.y());
56+
} else {
57+
// e.g. 5=2/x -> 5x=2
58+
final var lValue = new Expression(constant, inverse, expression.y());
59+
return new Expression(lValue, Operation.IS_EQUAL, expression.x());
60+
}
61+
} else if (expression.y() instanceof Value) {
62+
// e.g. 5=x/2 -> 5*2=x -> 10=x
63+
final var lValue = new Expression(constant, inverse, expression.y()).simplify();
64+
return new Expression(lValue, Operation.IS_EQUAL, expression.x());
65+
}
66+
// cannot simplify further
67+
return this;
68+
} else if (x() instanceof final Expression expression && y() instanceof final Value constant) {
69+
// e.g. 5/x=2 or x/5=2
70+
final var inverse = expression.operation().inverse();
71+
if (expression.x() instanceof Value) {
72+
// e.g. 5/x=2 or x/5=2
73+
if (expression.operation().isSymmetric()) {
74+
// e.g. 2x=5 -> x=5*2 -> x=10
75+
final var rValue = new Expression(constant, inverse, expression.x()).simplify();
76+
return new Expression(expression.y(), Operation.IS_EQUAL, rValue);
77+
} else {
78+
// e.g. 5/x=2 -> 5=2x
79+
final var rValue = new Expression(constant, inverse, expression.y());
80+
return new Expression(expression.x(), Operation.IS_EQUAL, rValue);
81+
}
82+
} else if (expression.y() instanceof Value) {
83+
// e.g. x/5=2 -> x=2*5 -> x=10
84+
final var rValue = new Expression(constant, inverse, expression.y()).simplify();
85+
return new Expression(expression.x(), Operation.IS_EQUAL, rValue);
86+
}
87+
// cannot simplify further
88+
return this;
89+
}
90+
}
91+
return this;
92+
}
93+
94+
public String toString() {
95+
return "(" + x() + ") " + operation() + " (" + y() + ")";
96+
}
97+
}
98+
99+
record Value(long value) implements Simplification {
100+
public String toString() {
101+
return "" + value();
102+
}
103+
104+
public Simplification simplify() {
105+
return this;
106+
}
107+
}
108+
109+
record Variable() implements Simplification {
110+
public String toString() {
111+
return "x";
112+
}
113+
114+
public Simplification simplify() {
115+
return this;
116+
}
117+
}
118+
119+
public interface Job {
120+
long yell(final Map<String, Monkey> monkeys, final Map<String, Long> results);
121+
122+
Simplification simplify(final Map<String, Monkey> monkeys, final Map<String, Long> results);
123+
124+
static Job parse(final String string) {
125+
final var components = string.trim().split(" ");
126+
if (components.length == 1) {
127+
return Yell.parse(string.trim());
128+
}
129+
return Math.parse(components);
130+
}
131+
}
132+
133+
public enum Operation {
134+
Add {
135+
public long operate(final long x, final long y) {
136+
return x + y;
137+
}
138+
139+
public Operation inverse() {
140+
return Subtract;
141+
}
142+
143+
public boolean isSymmetric() {
144+
return true;
145+
}
146+
},
147+
Subtract {
148+
public long operate(final long x, final long y) {
149+
return x - y;
150+
}
151+
152+
public Operation inverse() {
153+
return Add;
154+
}
155+
156+
public boolean isSymmetric() {
157+
return false;
158+
}
159+
},
160+
Multiply {
161+
public long operate(final long x, final long y) {
162+
return x * y;
163+
}
164+
165+
public Operation inverse() {
166+
return Divide;
167+
}
168+
169+
public boolean isSymmetric() {
170+
return true;
171+
}
172+
},
173+
Divide {
174+
public long operate(final long x, final long y) {
175+
return x / y;
176+
}
177+
178+
public Operation inverse() {
179+
return Multiply;
180+
}
181+
182+
public boolean isSymmetric() {
183+
return false;
184+
}
185+
},
186+
IS_EQUAL {
187+
public long operate(final long x, final long y) {
188+
// what a horrible hack, who would do this?
189+
return x == y ? 1L : 0L;
190+
}
191+
192+
public Operation inverse() {
193+
return IS_EQUAL;
194+
}
195+
196+
public boolean isSymmetric() {
197+
return true;
198+
}
199+
};
200+
201+
public abstract long operate(long x, long y);
202+
203+
public abstract Operation inverse();
204+
205+
public abstract boolean isSymmetric();
206+
207+
public String toString() {
208+
return switch (this) {
209+
case Add -> "+";
210+
case Subtract -> "-";
211+
case Multiply -> "*";
212+
case Divide -> "/";
213+
case IS_EQUAL -> "=";
214+
};
215+
}
216+
217+
public static Operation parse(final String operator) {
218+
return switch (operator.trim()) {
219+
case "+" -> Add;
220+
case "-" -> Subtract;
221+
case "*" -> Multiply;
222+
case "/" -> Divide;
223+
default -> throw new IllegalArgumentException("Invalid operator: " + operator);
224+
};
225+
}
226+
}
227+
228+
public record Unknown() implements Job {
229+
public long yell(Map<String, Monkey> monkeys, Map<String, Long> results) {
230+
throw new UnsupportedOperationException(); // Oof
231+
}
232+
233+
public Simplification simplify(Map<String, Monkey> monkeys, Map<String, Long> results) {
234+
return new Variable();
235+
}
236+
}
237+
238+
record Yell(long number) implements Job {
239+
public long yell(Map<String, Monkey> monkeys, Map<String, Long> results) {
240+
return number;
241+
}
242+
243+
public Simplification simplify(Map<String, Monkey> monkeys, Map<String, Long> results) {
244+
return new Value(number());
245+
}
246+
247+
public static Yell parse(final String string) {
248+
return new Yell(Integer.parseInt(string));
249+
}
250+
}
251+
252+
public record Math(String monkeyX, Operation operation, String monkeyY) implements Job {
253+
254+
public long yell(Map<String, Monkey> monkeys, Map<String, Long> results) {
255+
final var x = getVariable(monkeyX(), monkeys, results);
256+
final var y = getVariable(monkeyY(), monkeys, results);
257+
return operation().operate(x, y);
258+
}
259+
260+
public Simplification simplify(Map<String, Monkey> monkeys, Map<String, Long> results) {
261+
final var x = monkeys.get(monkeyX()).simplify(monkeys, results);
262+
final var y = monkeys.get(monkeyY()).simplify(monkeys, results);
263+
if (x instanceof final Value xValue && y instanceof final Value yValue) {
264+
return new Value(operation().operate(xValue.value(), yValue.value()));
265+
}
266+
return new Expression(x, operation(), y);
267+
}
268+
269+
long getVariable(final String monkeyName, final Map<String, Monkey> monkeys, final Map<String, Long> results) {
270+
if (results.containsKey(monkeyName)) {
271+
return results.get(monkeyName);
272+
}
273+
final var result = monkeys.get(monkeyName).yell(monkeys, results);
274+
results.put(monkeyName, result);
275+
return result;
276+
}
277+
278+
public static Math parse(final String[] components) {
279+
final var monkeyX = components[0].trim();
280+
final var operation = Operation.parse(components[1].trim());
281+
final var monkeyY = components[2].trim();
282+
return new Math(monkeyX, operation, monkeyY);
283+
}
284+
}
285+
286+
protected static Map<String, Monkey> getInput() {
287+
final Map<String, Monkey> result = new HashMap<>();
288+
StreamSupport.stream(new LineSpliterator("day-21.txt"), false)
289+
.map(Monkey::parse)
290+
.forEach(monkey -> result.put(monkey.name(), monkey));
291+
return Collections.unmodifiableMap(result);
292+
}
293+
294+
@Test
295+
public final void part1() {
296+
final var monkeys = getInput();
297+
final var results = new HashMap<String, Long>();
298+
final var result = monkeys.get("root").yell(monkeys, results);
299+
300+
System.out.println("Part 1: " + result);
301+
}
302+
303+
@Test
304+
public final void part2() {
305+
final var monkeys = new HashMap<>(getInput());
306+
final var results = new HashMap<String, Long>();
307+
final var oldRoot = monkeys.get("root");
308+
final var oldJob = (Math) oldRoot.job();
309+
monkeys.put("root", new Monkey("root", new Math(oldJob.monkeyX(), Operation.IS_EQUAL, oldJob.monkeyY())));
310+
monkeys.put("humn", new Monkey("humn", new Unknown()));
311+
312+
var simplification = monkeys.get("root").simplify(monkeys, results);
313+
while (true) {
314+
final var candidate = simplification.simplify();
315+
if (candidate.equals(simplification)) {
316+
break;
317+
}
318+
simplification = candidate;
319+
}
320+
System.out.println("Part 2: " + simplification);
321+
}
322+
323+
}

src/test/resources/sample/day-21.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
root: pppw + sjmn
2+
dbpl: 5
3+
cczh: sllz + lgvd
4+
zczc: 2
5+
ptdq: humn - dvpt
6+
dvpt: 3
7+
lfqf: 4
8+
humn: 5
9+
ljgn: 2
10+
sjmn: drzm * dbpl
11+
sllz: 4
12+
pppw: cczh / lfqf
13+
lgvd: ljgn * ptdq
14+
drzm: hmdt - zczc
15+
hmdt: 32

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy