<p>Write a program to solve a Sudoku puzzle by filling the empty cells.</p>

<p>A sudoku solution must satisfy <strong>all of the following rules</strong>:</p>

<ol>
	<li>Each of the digits <code>1-9</code> must occur exactly once in each row.</li>
	<li>Each of the digits <code>1-9</code> must occur exactly once in each column.</li>
	<li>Each of the digits <code>1-9</code> must occur exactly once in each of the 9 <code>3x3</code> sub-boxes of the grid.</li>
</ol>

<p>The <code>&#39;.&#39;</code> character indicates empty cells.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/f/ff/Sudoku-by-L2G-20050714.svg/250px-Sudoku-by-L2G-20050714.svg.png" style="height:250px; width:250px" />
<pre>
<strong>Input:</strong> board = [[&quot;5&quot;,&quot;3&quot;,&quot;.&quot;,&quot;.&quot;,&quot;7&quot;,&quot;.&quot;,&quot;.&quot;,&quot;.&quot;,&quot;.&quot;],[&quot;6&quot;,&quot;.&quot;,&quot;.&quot;,&quot;1&quot;,&quot;9&quot;,&quot;5&quot;,&quot;.&quot;,&quot;.&quot;,&quot;.&quot;],[&quot;.&quot;,&quot;9&quot;,&quot;8&quot;,&quot;.&quot;,&quot;.&quot;,&quot;.&quot;,&quot;.&quot;,&quot;6&quot;,&quot;.&quot;],[&quot;8&quot;,&quot;.&quot;,&quot;.&quot;,&quot;.&quot;,&quot;6&quot;,&quot;.&quot;,&quot;.&quot;,&quot;.&quot;,&quot;3&quot;],[&quot;4&quot;,&quot;.&quot;,&quot;.&quot;,&quot;8&quot;,&quot;.&quot;,&quot;3&quot;,&quot;.&quot;,&quot;.&quot;,&quot;1&quot;],[&quot;7&quot;,&quot;.&quot;,&quot;.&quot;,&quot;.&quot;,&quot;2&quot;,&quot;.&quot;,&quot;.&quot;,&quot;.&quot;,&quot;6&quot;],[&quot;.&quot;,&quot;6&quot;,&quot;.&quot;,&quot;.&quot;,&quot;.&quot;,&quot;.&quot;,&quot;2&quot;,&quot;8&quot;,&quot;.&quot;],[&quot;.&quot;,&quot;.&quot;,&quot;.&quot;,&quot;4&quot;,&quot;1&quot;,&quot;9&quot;,&quot;.&quot;,&quot;.&quot;,&quot;5&quot;],[&quot;.&quot;,&quot;.&quot;,&quot;.&quot;,&quot;.&quot;,&quot;8&quot;,&quot;.&quot;,&quot;.&quot;,&quot;7&quot;,&quot;9&quot;]]
<strong>Output:</strong> [[&quot;5&quot;,&quot;3&quot;,&quot;4&quot;,&quot;6&quot;,&quot;7&quot;,&quot;8&quot;,&quot;9&quot;,&quot;1&quot;,&quot;2&quot;],[&quot;6&quot;,&quot;7&quot;,&quot;2&quot;,&quot;1&quot;,&quot;9&quot;,&quot;5&quot;,&quot;3&quot;,&quot;4&quot;,&quot;8&quot;],[&quot;1&quot;,&quot;9&quot;,&quot;8&quot;,&quot;3&quot;,&quot;4&quot;,&quot;2&quot;,&quot;5&quot;,&quot;6&quot;,&quot;7&quot;],[&quot;8&quot;,&quot;5&quot;,&quot;9&quot;,&quot;7&quot;,&quot;6&quot;,&quot;1&quot;,&quot;4&quot;,&quot;2&quot;,&quot;3&quot;],[&quot;4&quot;,&quot;2&quot;,&quot;6&quot;,&quot;8&quot;,&quot;5&quot;,&quot;3&quot;,&quot;7&quot;,&quot;9&quot;,&quot;1&quot;],[&quot;7&quot;,&quot;1&quot;,&quot;3&quot;,&quot;9&quot;,&quot;2&quot;,&quot;4&quot;,&quot;8&quot;,&quot;5&quot;,&quot;6&quot;],[&quot;9&quot;,&quot;6&quot;,&quot;1&quot;,&quot;5&quot;,&quot;3&quot;,&quot;7&quot;,&quot;2&quot;,&quot;8&quot;,&quot;4&quot;],[&quot;2&quot;,&quot;8&quot;,&quot;7&quot;,&quot;4&quot;,&quot;1&quot;,&quot;9&quot;,&quot;6&quot;,&quot;3&quot;,&quot;5&quot;],[&quot;3&quot;,&quot;4&quot;,&quot;5&quot;,&quot;2&quot;,&quot;8&quot;,&quot;6&quot;,&quot;1&quot;,&quot;7&quot;,&quot;9&quot;]]
<strong>Explanation:</strong>&nbsp;The input board is shown above and the only valid solution is shown below:

<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/3/31/Sudoku-by-L2G-20050714_solution.svg/250px-Sudoku-by-L2G-20050714_solution.svg.png" style="height:250px; width:250px" />
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>board.length == 9</code></li>
	<li><code>board[i].length == 9</code></li>
	<li><code>board[i][j]</code> is a digit or <code>&#39;.&#39;</code>.</li>
	<li>It is <strong>guaranteed</strong> that the input board has only one solution.</li>
</ul>

class Solution {
protected:
  vector<bool> seen = vector(9, false);

  vector<int> getRemainingValues(const vector<vector<int> > &board, const int row, const int col) {
    ranges::fill(seen.begin(), seen.end(), false);

    // check box
    const int top = row / 3 * 3;
    const int bottom = top + 3; // not inclusive
    const int left = col / 3 * 3;
    const int right = left + 3; // not inclusive

    for (int i = 0; i < board.size(); i++) {
      auto cRow = board[i];

      // check row
      if (i == row) {
        for (const int n: cRow) {
          if (n != -1)
            seen[n - 1] = true;
        }
        continue; // skip cRow for later checks as already checked
      }

      // check col
      if (cRow[col] != -1)
        seen[cRow[col] - 1] = true;

      // check box
      if (i >= top && i < bottom) {
        for (int j = left; j < right; j++) {
          if (j == col)
            continue; // already checked
          if (cRow[j] != -1)
            seen[cRow[j] - 1] = true;
        }
      }
    }

    vector<int> out;
    for (int i = 0; i < seen.size(); ++i) {
      if (seen[i] == true)
        continue;
      out.emplace_back(i + 1);
    }

    return out;
  }

  // checks a single value
  // note board should not contain num at this point
  // bool isValid(vector<vector<int>> &board, int row, int col, int num)
  // {
  //   vector<int> validNumbers = remainingValues(board, row, col);
  //   for (auto it = validNumbers.begin(); it != validNumbers.end(); it++)
  //   {
  //     if (num == *it)
  //     {
  //       return true;
  //     }
  //   }
  //   return false;
  // }

  bool solve(int idx, vector<pair<int, int> > &boxes, vector<vector<int> > &board) {
    recursionCount += 1;
    // keep doing boxes until we fill out the entire board
    // if we find an unsolvable box we undo the last recursion and search another branch
    if (idx == boxes.size()) {
#ifdef DEBUG
      cout << "idx" << idx << endl;
      printBoard(board);
#endif
      return true;
    }

    int row = boxes[idx].first;
    int col = boxes[idx].second;

    const vector<int> validValues = getRemainingValues(board, row, col);

    if (validValues.empty()) {
#ifdef DEBUG
      cout << format("Unable to continue DEPTH = {} | {},{} | no values remining {}", idx, row, col,
                     validValues.size())
           << endl;
      printBoard(board);
#endif
      return false;
    }

#ifdef DEBUG
    stringstream ss;
    for (const int &validValue : validValues)
    {
      ss << validValue << ',';
    }
    cout << format("Depth {}, {},{} values={}", idx, row, col, ss.str()) << endl;
#endif

    bool success = false;
    for (const int n: validValues) {
      // set possible value
      board[row][col] = n;

      // recurse
      success = solve(idx + 1, boxes, board);
      if (success)
        break;

      // undo
      board[row][col] = -1;
    }

    return success;
  }

  static int compareMissing(const vector<vector<int> > &complMap, const pair<int, int> &a,
                            const pair<int, int> &b) {
    return complMap[a.first][a.second] < complMap[b.first][b.second];
  }

  static char toChar(const int i) {
    if (i == -1)
      return '.';
    return static_cast<char>('0' + i);
  }

public:
  static inline int recursionCount = 0;

  void solveSudoku(vector<vector<char> > &outBoard) {
    vector<vector<int> > board;
    vector<pair<int, int> > missing;

    for (int i = 0; i < 9; i++) {
      vector<int> row;
      row.reserve(9);
      for (int j = 0; j < 9; j++) {
        row.emplace_back(-1);
      }
      board.push_back(row);
    }

    for (int row = 0; row < outBoard.size(); row++) {
      auto rowData = outBoard[row];
      for (int col = 0; col < rowData.size(); col++) {
        int n = rowData[col] - '0';
        if (n < 0)
          n = -1;
        if (n == -1)
          missing.emplace_back(row, col);
        board[row][col] = n;
      }
    }

    vector completionMap(9, vector(9, 0));
    for (auto [row, col]: missing) {
      completionMap[row][col] = static_cast<int>(getRemainingValues(board, row, col).size());
    }

    // optional
    // herustical optimization step, sort missing in order of most complete (smallest count to largest count)
    ranges::sort(missing.begin(), missing.end(),
                 [completionMap, this] // required local variables
                 // annon function in C++
             (const pair<int, int> &a, const pair<int, int> &b) {
                   return compareMissing(completionMap, a, b);
                 });

#ifdef DEBUG
    cout << "Start" << endl;
    printBoard(board);
    cout << endl;
#endif

    solve(0, missing, board);

#ifdef DEBUG
    cout << "End" << endl;
    printBoard(board);
    cout << endl;
#endif

    for (auto [row, col]: missing) {
      outBoard[row][col] = toChar(board[row][col]);
    }
  }

  static void printBoard(const vector<vector<char> > &board) {
    for (auto &it: board) {
      for (const char &c: it) {
        cout << c << ' ';
      }
      cout << endl;
    }
  }

  static void printBoard(const vector<vector<int> > &board) {
    for (auto &it: board) {
      for (const int &n: it) {
        cout << toChar(n) << ' ';
      }
      cout << endl;
    }
  }
};
68340