@@ -297,104 +297,100 @@ <h2 id="problem-name">Crossed Wires</h2>
297
297
using System.Collections.Generic;
298
298
using System.Linq;
299
299
using System.Text.RegularExpressions;
300
+ using Circuit = System.Collections.Generic.Dictionary<string, Gate>;
300
301
301
- record struct Rule (string in1, string in2, string kind, string output );
302
+ record struct Gate (string in1, string kind, string in2 );
302
303
303
304
[ProblemName("Crossed Wires")]
304
305
class Solution : Solver {
305
306
306
307
public object PartOne(string input) {
307
- var gate = Parse(input);
308
- var bits = gate.Keys.Where(k => k.StartsWith("z")).OrderByDescending(x => x).ToArray();
308
+ var (inputs, circuit) = Parse(input);
309
+
310
+ var outputs = from label in circuit.Keys where label.StartsWith("z") select label;
311
+
309
312
var res = 0L;
310
- foreach (var b in bits ) {
311
- res = res * 2 + gate[b]( );
313
+ foreach (var label in outputs.OrderByDescending(label=>label) ) {
314
+ res = res * 2 + Evaluate(label, circuit, inputs );
312
315
}
313
316
return res;
314
317
}
315
318
319
+ int Evaluate(string label, Circuit circuit, Dictionary<string, int> inputs) {
320
+ if (inputs.TryGetValue(label, out var res)) {
321
+ return res;
322
+ } else {
323
+ return circuit[label] switch {
324
+ Gate(var in1, "AND", var in2) => Evaluate(in1, circuit, inputs) & Evaluate(in2, circuit, inputs),
325
+ Gate(var in1, "OR", var in2) => Evaluate(in1, circuit, inputs) | Evaluate(in2, circuit, inputs),
326
+ Gate(var in1, "XOR", var in2) => Evaluate(in1, circuit, inputs) ^ Evaluate(in2, circuit, inputs),
327
+ _ => throw new Exception(circuit[label].ToString()),
328
+ };
329
+ }
330
+ }
331
+
316
332
public object PartTwo(string input) {
317
- var swaps = Fix(ParseRules( input.Split("\n\n")[1])) ;
318
- return string.Join(",", swaps .OrderBy(x => x ));
333
+ var circuit = Parse( input).circuit ;
334
+ return string.Join(",", Fix(circuit) .OrderBy(label => label ));
319
335
}
320
336
321
- // the rules should define a full adder for two 44 bit numbers
337
+ // the circuit should define a full adder for two 44 bit numbers
322
338
// this fixer is specific to my input.
323
- IEnumerable<string> Fix(List<Rule> rules ) {
324
- var cin = Output(rules , "x00", "AND", "y00");
339
+ IEnumerable<string> Fix(Circuit circuit ) {
340
+ var cin = Output(circuit , "x00", "AND", "y00");
325
341
for (var i = 1; i < 45; i++) {
326
342
var x = $"x{i:D2}";
327
343
var y = $"y{i:D2}";
328
344
var z = $"z{i:D2}";
329
345
330
- var xor1 = Output(rules, x, "XOR", y);
331
- var and1 = Output(rules, x, "AND", y);
332
-
333
- var and2 = Output(rules, cin, "AND", xor1);
334
- var xor2 = Output(rules, cin, "XOR", xor1);
346
+ var xor1 = Output(circuit, x, "XOR", y);
347
+ var and1 = Output(circuit, x, "AND", y);
348
+ var xor2 = Output(circuit, cin, "XOR", xor1);
349
+ var and2 = Output(circuit, cin, "AND", xor1);
335
350
336
351
if (xor2 == null && and2 == null) {
337
- return Swap(rules , xor1, and1);
352
+ return SwapAndFix(circuit , xor1, and1);
338
353
}
339
354
340
- var carry = Output(rules , and1, "OR", and2);
355
+ var carry = Output(circuit , and1, "OR", and2);
341
356
if (xor2 != z) {
342
- return Swap(rules,z, xor2);
357
+ return SwapAndFix(circuit, z, xor2);
343
358
} else {
344
359
cin = carry;
345
360
}
346
361
}
347
362
return [];
348
363
}
349
364
350
- string Output(IEnumerable<Rule> rules, string x, string gate, string y) =>
351
- rules.SingleOrDefault(rule =>
352
- (rule.in1 == x && rule.kind == gate && rule.in2 == y) ||
353
- (rule.in1 == y && rule.kind == gate && rule.in2 == x)
354
- ).output;
355
-
356
- IEnumerable<string> Swap(List<Rule> rules, string out1, string out2) {
357
- rules = rules.Select(rule =>
358
- rule.output == out1 ? rule with {output = out2} :
359
- rule.output == out2 ? rule with {output = out1} :
360
- rule
361
- ).ToList();
362
-
363
- return Fix(rules).Concat([out1, out2]);
365
+ IEnumerable<string> SwapAndFix(Circuit circuit, string out1, string out2) {
366
+ (circuit[out1], circuit[out2]) = (circuit[out2], circuit[out1]);
367
+ return Fix(circuit).Concat([out1, out2]);
364
368
}
365
369
366
- List<Rule> ParseRules(string input) => input
367
- .Split("\n")
368
- .Select(line => {
369
- var parts = line.Split(" ");
370
- return new Rule(in1: parts[0], in2: parts[2], kind: parts[1], output: parts[4]);
371
- })
372
- .ToList();
373
- Dictionary<string, Gate> Parse(string input) {
370
+ string Output(Circuit circuit, string x, string kind, string y) =>
371
+ circuit.SingleOrDefault(pair =>
372
+ (pair.Value.in1 == x && pair.Value.kind == kind && pair.Value.in2 == y) ||
373
+ (pair.Value.in1 == y && pair.Value.kind == kind && pair.Value.in2 == x)
374
+ ).Key;
374
375
375
- var res = new Dictionary<string, Gate>();
376
+ (Dictionary<string, int> inputs, Circuit circuit) Parse(string input) {
377
+ var inputs = new Dictionary<string, int>();
378
+ var circuit = new Circuit();
376
379
377
380
var blocks = input.Split("\n\n");
378
381
379
382
foreach (var line in blocks[0].Split("\n")) {
380
383
var parts = line.Split(": ");
381
- res .Add(parts[0], () => int.Parse(parts[1]));
384
+ inputs .Add(parts[0], int.Parse(parts[1]));
382
385
}
383
386
384
387
foreach (var line in blocks[1].Split("\n")) {
385
388
var parts = Regex.Matches(line, "[a-zA-z0-9]+").Select(m => m.Value).ToArray();
386
- Gate gate = (parts[0], parts[1], parts[2]) switch {
387
- (var in1, "AND", var in2) => () => res[in1]() & res[in2](),
388
- (var in1, "OR", var in2) => () => res[in1]() | res[in2](),
389
- (var in1, "XOR", var in2) => () => res[in1]() ^ res[in2](),
390
- _ => throw new Exception(),
391
- };
392
- res.Add(parts[3], gate);
389
+ circuit.Add(parts[3], new Gate(in1: parts[0], kind: parts[1], in2: parts[2]));
393
390
}
394
- return res ;
391
+ return (inputs, circuit) ;
395
392
}
396
393
397
- delegate int Gate();
398
394
}</ code > </ pre > </ div >
399
395
< div id ="code-location "> < p > Please ☆ my < a href ="https://github.com/encse/adventofcode/ "> repo</ a > if you like it!</ p > </ div >
400
396
</ div >
0 commit comments