Day 10: Hoof It

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
    1
    ·
    edit-2
    2 months ago

    Dart

    I dug out the hill-climbing trail-walking code from 2022 Day 12, put it up on blocks, and stripped all the weirdness out of it.

    Ended up with just a simple flood-fill from each trailhead, so it turns out I only actually used the Graph and Node classes which I then also stripped out…

    import 'dart:math';
    import 'package:collection/collection.dart';
    import 'package:more/more.dart';
    
    const dirs = [Point(0, 1), Point(0, -1), Point(1, 0), Point(-1, 0)];
    late Map<Point<int>, int> nodes;
    late Map<Point<int>, List<Point<int>>> nexts;
    
    List<Point<int>> parse(List<String> lines) {
      nodes = {
        for (var y in 0.to(lines.length))
          for (var x in 0.to(lines.first.length))
            Point(x, y): int.parse(lines[y][x])
      };
      nexts = Map.fromEntries(nodes.keys.map((n) => MapEntry(
          n,
          dirs
              .map((d) => n + d)
              .where((d) => (nodes[d] ?? -1) - nodes[n]! == 1)
              .toList())));
      return nodes.keys.where((e) => nodes[e] == 0).toList();
    }
    
    Set<Point> countEnds(Point here, [sofar = const <Point>{}]) {
      if (nodes[here]! == 9) return {here};
      var frontier = nexts[here]!.where((e) => !sofar.contains(e));
      return frontier
          .map((e) => countEnds(e, sofar.toSet()..add(e)))
          .flattened
          .toSet();
    }
    
    int countPaths(Point here, [sofar = const <Point>{}]) {
      if (nodes[here]! == 9) return 1;
      var frontier = nexts[here]!.where((e) => !sofar.contains(e));
      return frontier.map((e) => countPaths(e, sofar.toSet()..add(e))).sum;
    }
    
    part1(List<String> lines) => parse(lines).map((s) => countEnds(s).length).sum;
    part2(List<String> lines) => parse(lines).map((s) => countPaths(s)).sum;