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

  • mykl@lemmy.world
    link
    fedilink
    arrow-up
    3
    ·
    edit-2
    2 days ago

    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 + '| ');
    }