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

     1  class Octo {
     2    int x, y, value;
     3    Octo(this.x, this.y, this.value);
     4  
     5    @override
     6    int get hashCode => Object.hashAll([y, x]);
     7  
     8    @override
     9    bool operator ==(Object other) {
    10      return other is Octo &&
    11          other.runtimeType == runtimeType &&
    12          other.y == y &&
    13          other.x == x;
    14    }
    15  
    16    bool increment() {
    17      value++;
    18      if (value > 9) {
    19        value = 0;
    20        return true;
    21      }
    22      return false;
    23    }
    24  }
    25  
    26  class OctoSim {
    27    late final List<List<Octo>> octos;
    28    int flashes = 0;
    29  
    30    int get octoCount =>
    31        octos.fold(0, (tot, row) => tot + row.fold(0, (prev, _) => prev + 1));
    32  
    33    OctoSim({
    34      required rows,
    35    }) {
    36      initOctos(rows);
    37    }
    38  
    39    void initOctos(List<List<int>> rows) {
    40      List<List<Octo>> octos = [];
    41      for (var y = 0; y < rows.length; y++) {
    42        var row = rows[y];
    43        var octoRow = <Octo>[];
    44        for (var x = 0; x < row.length; x++) {
    45          var value = row[x];
    46          var octo = Octo(x, y, value);
    47          octoRow.add(octo);
    48        }
    49        octos.add(octoRow);
    50      }
    51      this.octos = octos;
    52    }
    53  
    54    int iterateOctos(int iterations) {
    55      for (var i = 0; i < iterations; i++) {
    56        iterate();
    57      }
    58      return flashes;
    59    }
    60  
    61    int findFirstSimultaneousFlash() {
    62      int iterations = 0;
    63      while (true) {
    64        iterations++;
    65        var currentFlashCount = iterate();
    66        if (currentFlashCount >= octoCount) {
    67          break;
    68        }
    69      }
    70      return iterations;
    71    }
    72  
    73    int iterate() {
    74      var flashed = <Octo>{};
    75      var currentFlashCount = 0;
    76      for (var y = 0; y < octos.length; y++) {
    77        var octoRow = octos[y];
    78        for (var x = 0; x < octoRow.length; x++) {
    79          var octo = octoRow[x];
    80          currentFlashCount += processOcto(octo, flashed);
    81        }
    82      }
    83      return currentFlashCount;
    84    }
    85  
    86    int processOcto(Octo octo, Set<Octo> flashed) {
    87      if (flashed.contains(octo)) {
    88        return 0;
    89      }
    90      var didFlash = octo.increment();
    91      if (didFlash) {
    92        flashed.add(octo);
    93        flashes++;
    94        return 1 +
    95            findValidNeighbours(octo)
    96                .fold(0, (total, o) => total + processOcto(o, flashed));
    97      }
    98      return 0;
    99    }
   100  
   101    List<Octo> findValidNeighbours(Octo octo) {
   102      var valids = <Octo>[];
   103      var x = octo.x;
   104      var y = octo.y;
   105      var upOk = y > 0;
   106      var downOk = y < octos.length - 1;
   107      var leftOk = x > 0;
   108      var rightOk = x < octos[y].length - 1;
   109      if (upOk) {
   110        valids.add(octos[y - 1][x]);
   111        if (rightOk) {
   112          valids.add(octos[y - 1][x + 1]);
   113        }
   114        if (leftOk) {
   115          valids.add(octos[y - 1][x - 1]);
   116        }
   117      }
   118      if (rightOk) {
   119        valids.add(octos[y][x + 1]);
   120      }
   121      if (downOk) {
   122        valids.add(octos[y + 1][x]);
   123        if (rightOk) {
   124          valids.add(octos[y + 1][x + 1]);
   125        }
   126        if (leftOk) {
   127          valids.add(octos[y + 1][x - 1]);
   128        }
   129      }
   130      if (leftOk) {
   131        valids.add(octos[y][x - 1]);
   132      }
   133      return valids;
   134    }
   135  }