github.com/cycloss/advent-of-code@v0.0.0-20221210145555-15039b95faa6/2021/day9/day9-2.dart (about)

     1  import 'dart:convert';
     2  import 'dart:io';
     3  
     4  void main() async {
     5    Stream<String> lines = File("day9.txt")
     6        .openRead()
     7        .transform(Utf8Decoder())
     8        .transform(LineSplitter());
     9    var rows = <List<int>>[];
    10    await for (var line in lines) {
    11      var split = line.split("");
    12      var rowNums = <int>[];
    13      for (var raw in split) {
    14        rowNums.add(int.parse(raw));
    15      }
    16      rows.add(rowNums);
    17    }
    18  
    19    var basinSizes = <int>[];
    20  
    21    for (var i = 0; i < rows.length; i++) {
    22      var row = rows[i];
    23      for (var j = 0; j < row.length; j++) {
    24        var num = row[j];
    25        var adjacents = <int>[];
    26  
    27        if (j > 0) {
    28          var left = row[j - 1];
    29          adjacents.add(left);
    30        }
    31        if (j < row.length - 1) {
    32          var right = row[j + 1];
    33          adjacents.add(right);
    34        }
    35        if (i > 0) {
    36          var up = rows[i - 1][j];
    37          adjacents.add(up);
    38        }
    39        if (i < rows.length - 1) {
    40          var down = rows[i + 1][j];
    41          adjacents.add(down);
    42        }
    43  
    44        var lowPoint = true;
    45        for (var n in adjacents) {
    46          if (num >= n) {
    47            lowPoint = false;
    48          }
    49        }
    50        if (lowPoint) {
    51          var visitedSet = <Vector2>{};
    52          var size = findBasinSize(rows, visitedSet, Vector2(i, j));
    53          print(size);
    54          basinSizes.add(size);
    55        }
    56      }
    57    }
    58    basinSizes.sort((a, b) => b - a);
    59    var ans = basinSizes[0] * basinSizes[1] * basinSizes[2];
    60  
    61    print("Part 2 Solution: $ans");
    62  }
    63  
    64  class Vector2 {
    65    int i, j;
    66    Vector2(this.i, this.j);
    67  
    68    int value(List<List<int>> rows) {
    69      return rows[i][j];
    70    }
    71  
    72    @override
    73    int get hashCode => Object.hashAll([i, j]);
    74  
    75    @override
    76    bool operator ==(Object other) {
    77      return other is Vector2 &&
    78          other.runtimeType == runtimeType &&
    79          other.i == i &&
    80          other.j == j;
    81    }
    82  }
    83  
    84  int findBasinSize(List<List<int>> rows, Set<Vector2> visitedSet, Vector2 v2) {
    85    if (visitedSet.contains(v2)) {
    86      // already visited
    87      return 0;
    88    }
    89    if (v2.value(rows) == 9) {
    90      // got to edge
    91      visitedSet.add(v2);
    92      return 0;
    93    }
    94    visitedSet.add(v2);
    95  
    96    var adjacents = <Vector2>[];
    97    // add all valid adjacents
    98    var row = rows[v2.i];
    99    var i = v2.i;
   100    var j = v2.j;
   101    if (j > 0) {
   102      adjacents.add(Vector2(i, j - 1));
   103    }
   104    if (j < row.length - 1) {
   105      adjacents.add(Vector2(i, j + 1));
   106    }
   107    if (i > 0) {
   108      adjacents.add(Vector2(i - 1, j));
   109    }
   110    if (i < rows.length - 1) {
   111      adjacents.add(Vector2(i + 1, j));
   112    }
   113    var total =
   114        adjacents.fold<int>(0, (t, e) => t + findBasinSize(rows, visitedSet, e));
   115  
   116    return 1 + total;
   117  }