Rules: no spoilers.

The other rules are made up as we go along.

Share code by link to a forge, home page, pastebin (Eric Wastl has one here) or code section in a comment.

  • swlabr@awful.systems
    link
    fedilink
    English
    arrow-up
    3
    ·
    edit-2
    11 months ago
    3b redux

    I took out the union find, the code is simpler and more readable now. I also leaned in to using null values, which is gross but whatever, it works.

    void day3s() {
      List lines = [
        for (String? line = stdin.readLineSync();
            line != null;
            line = stdin.readLineSync())
          line
      ];
    
      // lazy processing + memoization
      List> digs = [for (int i = 0; i < lines.length; i++) Map()];
      int? isDigitMem(int r, int c) {
        if (r < 0 || r > lines.length || c < 0 || c > lines[0].length) return null;
        return digs[r].putIfAbsent(c, () => isDigit(lines[r][c]));
      }
    
      int stoi(int row, int col) {
        int acc = 0;
        for (int i = col; i < lines[0].length; i++) {
          int? d = isDigitMem(row, i);
          if (d != null) {
            acc = (acc * 10) + d;
          } else {
            break;
          }
        }
        return acc;
      }
    
      int? stoiSearch(int row, int col) {
        assert(row >= 0 && col >= 0 && row < lines.length && col < lines[0].length);
        if (isDigitMem(row, col) == null) {
          return null;
        }
        int i = col - 1;
        while (i >= 0) {
          if (isDigitMem(row, i) == null) {
            return stoi(row, i + 1);
          }
          i--;
        }
        return stoi(row, 0);
      }
    
      List> s2i = [for (int i = 0; i < lines.length; i++) Map()];
      int? stoiSearchMem(int row, int col) {
        if (row < 0 || row >= lines.length) return null;
        if (col < 0 || col >= lines[0].length) return null;
        return s2i[row].putIfAbsent(col, () => stoiSearch(row, col));
      }
    
      int count = 0;
      for (int i = 0; i < lines.length; i++) {
        for (int j = 0; j < lines[0].length; j++) {
          if (lines[i][j] != "*") {
            continue;
          }
    
          List gearVals = List.empty(growable: true);
          for (int x = -1; x <= 1; x++) {
            int? left = stoiSearchMem(i + x, j - 1);
            int? mid = stoiSearchMem(i + x, j);
            int? right = stoiSearchMem(i + x, j + 1);
    
            if (isDigitMem(i + x, j) == null) {
              if (left != null) {
                gearVals.add(left);
              }
    
              if (right != null) {
                gearVals.add(right);
              }
            } else if (left != null) {
              gearVals.add(left);
            } else if (mid != null) {
              gearVals.add(mid);
            } else if (right != null) {
              gearVals.add(right);
            }
          }
    
          if (gearVals.length == 2) {
            count += gearVals[0] * gearVals[1];
          }
        }
      }
    
      print(count);
    }