<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 {
public:
    void solveSudoku(vector<vector<char>>& board) {
        row_cache = vector<set<char>>(board.size(), set<char>());
        col_cache = vector<set<char>>(board.size(), set<char>());
        sq_cache  = vector<set<char>>(board.size(), set<char>());

        for (int i = 0; i < board.size(); i++)
        {
            for (int j = 0; j < board.size(); j++)
            {
                if (board[i][j] != '.')
                {
                    row_cache[i].insert(board[i][j]);
                }
            }
        }

        for (int j = 0; j < board.size(); j++)
        {
            for (int i = 0; i < board.size(); i++)
            {
                if (board[i][j] != '.')
                {
                    col_cache[j].insert(board[i][j]);
                }
            }
        }

        for (int i = 0; i < board.size(); i+=3)
        {
            for (int j = 0; j < board.size(); j+=3)
            {
                int square_index = 3*(i/3) + j/3;
                for (int a = i; a < i+3; a++)
                {
                    for (int b = j; b < j+3; b++)
                    {
                        if (board[a][b] != '.')
                        {
                            sq_cache[square_index].insert(board[a][b]);
                        }
                    }
                }
            }
        }
        // for (int i = 0; i < row_cache.size(); ++i) {
        //     std::cout << "Row " << i << ": ";
        //     for (char c : row_cache[i]) {
        //         std::cout << c << " ";
        //     }
        //     std::cout << std::endl;
        // }

        Coordinate coord({0, 0}, board.size());
        bool r = backtrack(board, coord);

        // for (int i = 0; i < row_cache.size(); ++i) {
        //     std::cout << "Row " << i << ": ";
        //     for (char c : row_cache[i]) {
        //         std::cout << c << " ";
        //     }
        //     std::cout << std::endl;
        // }
        
    }

    class Coordinate
    {
    public:
        pair<int, int> coordinate;
        int board_size;

        Coordinate(pair<int, int> c, int bs)
        {
            coordinate = c;
            board_size = bs;
        }

        void Next()
        {
            auto [x, y] = coordinate;
            if (x == board_size-1 && y == board_size-1)
            {
                return;
            }
            else if (y == board_size-1)
            {
                x++;
            }
            y = (y+1) % (board_size); 
            coordinate = {x, y};
        }

        void Back()
        {
            auto [x, y] = coordinate;
            if (y == 0)
            {
                x--;
            }
            y = board_size-1;
            coordinate = {x, y};
        }
    };

    bool backtrack(auto &board, Coordinate coord)
    {
        auto [x, y] = coord.coordinate;
        if (board[x][y] != '.')
        {
            if (x == board.size()-1 && y == board.size()-1)
            {
                return true;
            }
            coord.Next();
            return backtrack(board, coord);
        }
        else
        {
            // cout << "x : " << x << " y : " << y << endl;
            int square_index = 3*(x/3) + y/3;
            for (char digit = '1'; digit <= '9'; digit++)
            {
                if (row_cache[x].contains(digit)
                    || col_cache[y].contains(digit)
                    || sq_cache[square_index].contains(digit))
                {
                    continue;
                }

                row_cache[x].insert(digit);
                col_cache[y].insert(digit);
                sq_cache[square_index].insert(digit);
                board[x][y] = digit;
                Coordinate tmp_coord = coord;
                coord.Next();
                bool result = backtrack(board, coord);

                if (result)
                {
                    board[x][y] = digit;
                    return true;
                }
                else
                {
                    row_cache[x].erase(digit);
                    col_cache[y].erase(digit);
                    sq_cache[square_index].erase(digit);
                    coord = tmp_coord;
                    board[x][y] = '.';

                }

            }
        }
        return false;
    }

    vector<set<char>> row_cache;
    vector<set<char>> col_cache;
    vector<set<char>> sq_cache;

    
};
25234