Day 24: Crossed Wires
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
Dart
Not very happy with this, as for part 2 the code just told me which four pairs of bits of the output needed investigation and I then tediously worked through how they differed from the correct adder implementation in the debugger.
Spoilered as it is overly long and not very interesting.
spoiler
import 'package:collection/collection.dart'; import 'package:more/more.dart'; var nodes = <String, Node>{}; class Node { String name = ''; bool? state; var outputGates = <String>[]; } class Wire implements Node { @override String name; @override bool? state; @override var outputGates = <String>[]; Wire(this.name, this.state); set() { for (var g in outputGates) { (nodes[g]! as Gate).set(); } } } class Gate implements Node { String input1, input2, type; @override String name; @override bool? state; @override var outputGates = <String>[]; Gate(this.name, this.input1, this.input2, this.type); set() { var a = nodes[input1]!.state; var b = nodes[input2]!.state; if (a == null || b == null) return; state = switch (type) { 'AND' => a && b, 'OR' => a || b, _ => a ^ b }; for (var g in outputGates) { (nodes[g]! as Gate).set(); } } } void setup(List<String> lines) { var parts = lines.splitAfter((e) => e.isEmpty); Map<String, Node> wires = Map.fromEntries(parts.first.skipLast(1).map((e) { var p = e.split(': '); return MapEntry(p[0], Wire(p[0], p[1] == '1')); })); nodes = Map.fromEntries(parts.last.map((e) { var p = e.split(' '); return MapEntry(p.last, Gate(p.last, p[0], p[2], p[1])); })); nodes.addAll(wires); for (var g in nodes.values) { if (g is! Gate) continue; nodes[g.input1]!.outputGates.add(g.name); nodes[g.input2]!.outputGates.add(g.name); } } String line(String s) => nodes.keys .where((e) => e.startsWith(s)) .sorted() .reversed .map((e) => nodes[e]!.state! ? '1' : '0') .join(''); part1(List<String> lines) { setup(lines); nodes.values.whereType<Wire>().forEach((e) => e.set()); return int.parse(line('z'), radix: 2); } part2(List<String> lines) { setup(lines); var bits = nodes.keys.count((e) => e.startsWith('x')); for (var b in 0.to(bits)) { nodes.values.whereType<Gate>().forEach((e) => e.state = null); nodes.values.whereType<Wire>().forEach(((e) => e.state = false)); nodes['y${b.toString().padLeft(2, "0")}']!.state = true; nodes.values.whereType<Wire>().forEach((e) => e.set()); print('${line("x")}\t${line("y")}\t${line("z")}\t$b'); var output = line('z'); for (var i in 0.to(bits)) { if (output[bits - i] != ((i == b) ? "1" : "0")) print(i); } } tree('z05'); tree('z06'); // Add break point here and inspect and solve manually using `tree`. print('break here'); } tree(String s, {indent = ''}) { var here = nodes[s]!; if (here is Wire) { print('$indent${here.name} (wire)'); return; } here as Gate; print('$indent${here.name} ${here.type}'); tree(here.input1, indent: indent + '| '); tree(here.input2, indent: indent + '| '); }