1
+ package com .macasaet ;
2
+
3
+ import org .junit .jupiter .api .Disabled ;
4
+ import org .junit .jupiter .api .Nested ;
5
+ import org .junit .jupiter .api .Test ;
6
+
7
+ import java .math .BigInteger ;
8
+ import java .util .ArrayList ;
9
+ import java .util .List ;
10
+ import java .util .PrimitiveIterator ;
11
+ import java .util .concurrent .atomic .AtomicInteger ;
12
+ import java .util .function .Consumer ;
13
+ import java .util .function .Supplier ;
14
+ import java .util .stream .Stream ;
15
+ import java .util .stream .StreamSupport ;
16
+
17
+ import static org .junit .jupiter .api .Assertions .assertEquals ;
18
+
19
+ /**
20
+ * --- Day 24: Arithmetic Logic Unit ---
21
+ */
22
+ public class Day24 {
23
+
24
+ protected Stream <String > getInput () {
25
+ return StreamSupport
26
+ .stream (new LineSpliterator ("day-24.txt" ),
27
+ false );
28
+ }
29
+
30
+ public static class ArithmeticLogicUnit {
31
+ public BigInteger getW () {
32
+ return w ;
33
+ }
34
+
35
+ public void setW (BigInteger w ) {
36
+ this .w = w ;
37
+ }
38
+
39
+ public BigInteger getX () {
40
+ return x ;
41
+ }
42
+
43
+ public void setX (BigInteger x ) {
44
+ this .x = x ;
45
+ }
46
+
47
+ public BigInteger getY () {
48
+ return y ;
49
+ }
50
+
51
+ public void setY (BigInteger y ) {
52
+ this .y = y ;
53
+ }
54
+
55
+ public BigInteger getZ () {
56
+ return z ;
57
+ }
58
+
59
+ public void setZ (BigInteger z ) {
60
+ this .z = z ;
61
+ }
62
+
63
+ private BigInteger w = BigInteger .ZERO , x = BigInteger .ZERO , y = BigInteger .ZERO , z = BigInteger .ZERO ;
64
+
65
+ public List <? extends Instruction > getInstructions () {
66
+ return instructions ;
67
+ }
68
+
69
+ public void setInstructions (List <? extends Instruction > instructions ) {
70
+ this .instructions = instructions ;
71
+ }
72
+
73
+ private List <? extends Instruction > instructions = new ArrayList <>();
74
+
75
+ public boolean isValid (final String modelNumber ) {
76
+ final var iterator = modelNumber .chars ().map (Character ::getNumericValue ).iterator ();
77
+ for (final var instruction : getInstructions ()) {
78
+ instruction .evaluate (iterator );
79
+ }
80
+ return BigInteger .ZERO .equals (getZ ());
81
+ }
82
+
83
+ public static ArithmeticLogicUnit parse (final Stream <String > lines ) {
84
+ final var result = new ArithmeticLogicUnit ();
85
+ final List <? extends Instruction > instructions = lines .map (line -> {
86
+ final var components = line .split (" " );
87
+
88
+ final Consumer <BigInteger > resultSetter = switch (components [1 ]) {
89
+ case "w" -> result ::setW ;
90
+ case "x" -> result ::setX ;
91
+ case "y" -> result ::setY ;
92
+ case "z" -> result ::setZ ;
93
+ default -> throw new IllegalArgumentException ("Invalid instruction, invalid l-value: " + line );
94
+ };
95
+ final Supplier <BigInteger > xSupplier = switch (components [1 ]) {
96
+ case "w" -> result ::getW ;
97
+ case "x" -> result ::getX ;
98
+ case "y" -> result ::getY ;
99
+ case "z" -> result ::getZ ;
100
+ default -> throw new IllegalArgumentException ("Invalid instruction, invalid l-value: " + line );
101
+ };
102
+ final Supplier <BigInteger > ySupplier = components .length > 2 ? switch (components [2 ]) {
103
+ case "w" -> result ::getW ;
104
+ case "x" -> result ::getX ;
105
+ case "y" -> result ::getY ;
106
+ case "z" -> result ::getZ ;
107
+ default -> () -> new BigInteger (components [2 ]);
108
+ } : () -> {
109
+ throw new IllegalStateException ();
110
+ };
111
+ return switch (components [0 ]) {
112
+ case "inp" -> new Input (resultSetter );
113
+ case "add" -> new Add (resultSetter , xSupplier , ySupplier );
114
+ case "mul" -> new Multiply (resultSetter , xSupplier , ySupplier );
115
+ case "div" -> new Divide (resultSetter , xSupplier , ySupplier );
116
+ case "mod" -> new Modulo (resultSetter , xSupplier , ySupplier );
117
+ case "eql" -> new Equals (resultSetter , xSupplier , ySupplier );
118
+ default -> throw new IllegalArgumentException ("Invalid instruction: " + line );
119
+ };
120
+ }).toList ();
121
+ result .setInstructions (instructions );
122
+ return result ;
123
+ }
124
+
125
+ public void reset () {
126
+ setW (BigInteger .ZERO );
127
+ setX (BigInteger .ZERO );
128
+ setY (BigInteger .ZERO );
129
+ setZ (BigInteger .ZERO );
130
+ }
131
+ }
132
+
133
+ public interface Instruction {
134
+ void evaluate (PrimitiveIterator .OfInt input );
135
+ }
136
+
137
+ public record Input (Consumer <BigInteger > setter ) implements Instruction {
138
+
139
+ public void evaluate (PrimitiveIterator .OfInt input ) {
140
+ setter .accept (BigInteger .valueOf (input .nextInt ()));
141
+ }
142
+ }
143
+
144
+ public record Add (Consumer <BigInteger > resultSetter , Supplier <BigInteger > xSupplier ,
145
+ Supplier <BigInteger > ySupplier ) implements Instruction {
146
+ public void evaluate (PrimitiveIterator .OfInt _input ) {
147
+ resultSetter .accept (xSupplier .get ().add (ySupplier .get ()));
148
+ }
149
+ }
150
+
151
+ public record Multiply (Consumer <BigInteger > resultSetter , Supplier <BigInteger > xSupplier ,
152
+ Supplier <BigInteger > ySupplier ) implements Instruction {
153
+ public void evaluate (PrimitiveIterator .OfInt _input ) {
154
+ resultSetter .accept (xSupplier .get ().multiply (ySupplier .get ()));
155
+ }
156
+ }
157
+
158
+ public record Divide (Consumer <BigInteger > resultSetter , Supplier <BigInteger > xSupplier ,
159
+ Supplier <BigInteger > ySupplier ) implements Instruction {
160
+ public void evaluate (PrimitiveIterator .OfInt _input ) {
161
+ resultSetter .accept (xSupplier .get ().divide (ySupplier .get ()));
162
+ }
163
+ }
164
+
165
+ public record Modulo (Consumer <BigInteger > resultSetter , Supplier <BigInteger > xSupplier ,
166
+ Supplier <BigInteger > ySupplier ) implements Instruction {
167
+ public void evaluate (PrimitiveIterator .OfInt _input ) {
168
+ resultSetter .accept (xSupplier .get ().mod (ySupplier .get ()));
169
+ }
170
+ }
171
+
172
+ public record Equals (Consumer <BigInteger > resultSetter , Supplier <BigInteger > xSupplier ,
173
+ Supplier <BigInteger > ySupplier ) implements Instruction {
174
+ public void evaluate (PrimitiveIterator .OfInt _input ) {
175
+ resultSetter .accept (xSupplier .get ().equals (ySupplier .get ()) ? BigInteger .ONE : BigInteger .ZERO );
176
+ }
177
+ }
178
+
179
+ @ Nested
180
+ public class ArithmeticLogicUnitTest {
181
+ @ Disabled
182
+ @ Test
183
+ public void testNegation () {
184
+ // given
185
+ final var input = """
186
+ inp x
187
+ mul x -1
188
+ """ ;
189
+ final var alu = ArithmeticLogicUnit .parse (input .lines ());
190
+
191
+ // when
192
+ alu .isValid ("7" );
193
+
194
+ // then
195
+ assertEquals (-7 , alu .getX ());
196
+ }
197
+
198
+ @ Disabled
199
+ @ Test
200
+ public final void testThreeTimes () {
201
+ // given
202
+ final var input = """
203
+ inp z
204
+ inp x
205
+ mul z 3
206
+ eql z x
207
+ """ ;
208
+ final var alu = ArithmeticLogicUnit .parse (input .lines ());
209
+
210
+ // when
211
+ alu .isValid ("39" );
212
+
213
+ // then
214
+ assertEquals (1 , alu .getZ ());
215
+ }
216
+
217
+ @ Disabled
218
+ @ Test
219
+ public final void testBinaryConversion () {
220
+ // given
221
+ final var input = """
222
+ inp w
223
+ add z w
224
+ mod z 2
225
+ div w 2
226
+ add y w
227
+ mod y 2
228
+ div w 2
229
+ add x w
230
+ mod x 2
231
+ div w 2
232
+ mod w 2
233
+ """ ;
234
+ final var alu = ArithmeticLogicUnit .parse (input .lines ());
235
+
236
+ // when
237
+ alu .isValid ("9" );
238
+
239
+ // then
240
+ assertEquals (1 , alu .getW ());
241
+ assertEquals (0 , alu .getX ());
242
+ assertEquals (0 , alu .getY ());
243
+ assertEquals (1 , alu .getZ ());
244
+ }
245
+
246
+ @ Test
247
+ public final void testIsValid () {
248
+ // given
249
+ final var alu = ArithmeticLogicUnit .parse (getInput ());
250
+
251
+ // when
252
+ final var result = alu .isValid ("13579246899999" );
253
+
254
+ // then
255
+ System .err .println ("z=" + alu .getZ ());
256
+ }
257
+ }
258
+
259
+ @ Disabled
260
+ @ Test
261
+ public final void part1 () {
262
+ final var monad = getInput ().toList ();
263
+ final var counter = new AtomicInteger (0 );
264
+ final var result = Stream .iterate (new BigInteger ("99999999999999" ), previous -> previous .subtract (BigInteger .ONE ))
265
+ .parallel ()
266
+ .filter (candidate -> {
267
+ final int count = counter .updateAndGet (previous -> previous + 1 );
268
+ if (count % 10000 == 0 ) {
269
+ System .err .println ("Testing: " + candidate );
270
+ }
271
+ final var alu = ArithmeticLogicUnit .parse (monad .stream ());
272
+ return alu .isValid (candidate .toString ());
273
+ }).findFirst ();
274
+ System .out .println ("Part 1: " + result .orElseThrow ());
275
+ }
276
+
277
+ @ Disabled
278
+ @ Test
279
+ public final void part2 () {
280
+
281
+ System .out .println ("Part 2: " + null );
282
+ }
283
+
284
+ }
0 commit comments