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
You are viewing a single thread.
View all comments 3 points
*
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 + '| ');
}