#include <iostream>
#include <vector>
#include <utility>
#include <unordered_map>
using namespace std;
unordered_map<int, int> originNumber;
void setOrigin(vector<vector <char>>& board)
{
for (int i = 0; i <= 8; i++) {
for (int j = 0; j <= 8; j++) {
cout << i << ", " << j << " ";
if (board[i][j] != '.') {
originNumber[i*9+j] = 1;
cout << originNumber[i*9+j] << endl;
}
else{
cout << originNumber[i*9+j] << endl;
originNumber[i*9+j] = 0;
}
}
}
}
bool isOriginNumber(int row, int col)
{
return originNumber[row * 9 + col];
}
bool unique_in_row(vector<vector<char>>& board, int row, int col, char key)
{
for (int i = 0; i <= 8; i++) {
if (board[row][i] == key && i != col) {//存在同行不同列的相同元素
cout << key << "is not unique in row " << row << endl;
return false;
}
}
cout << key << "is unique in row " << row << endl;
return true;
}
bool unique_in_col(vector<vector<char>>& board, int row, int col, char key)
{
for (int i = 0; i <= 8; i++) {
if (board[i][col] == key && i != row) {//存在同列不同行的相同元素
cout << key << "is not unique in col " << col << endl;
return false;
}
}
cout << key << "is unique in col " << col << endl;
return true;
}
bool unique_in_square(vector<vector<char>>& board, int row, int col, char key)
{
//cout << "unique_in_square: ";
//cout << "row = " << row << " " << "col = " << col << endl;
int square_row = row % 3;
int square_col = col % 3;
//cout << "square_row = " << square_row << " " << "square_col = " << square_col << endl;
int startRow = row, startCol = col;
if (square_row == 1)
startRow = row - 1;
else if (square_row == 2)
startRow = row - 2;
if (square_col == 1)
startCol = col - 1;
else if (square_col == 2)
startCol = col - 2;
//cout << "startRow = " << startRow << " " << "startCol = " << startCol << endl;
for (int i = 0; i <= 2; i++) {
for (int j = 0; j <= 2; j++) {//存在同九宫格不同行列的相同元素
if (board[startRow+i][startCol+j] == key && startRow+i != row && startCol+j != col) {
cout << key << "is not unique in square " << endl;
return false;
}
}
}
cout << key << "is unique in square " << endl;
return true;
}
int helper(vector<vector<char>>& board, int row, int col)
{
if (row == 9) {
return row;
} else {
bool flag;
int nextrow = -1; //下一个空白处的行号
int nextcol = -1; //下一个空白处的列号
int j; //计算下一个空白处的辅助数据,标志是有有下一个空白的标记位
int depth = row; //已经递归到的深度
//更新到下一个位置,j == (board.size() * board[0].size())说明没有下一个空白处
for (j = row*9+col+1; j < (board.size() * board[0].size()); j++) {
if (originNumber[j] == 0) {
nextrow = j / 9;
nextcol = j % 9;
break;
}
}
//如果有下一个空位,则newrow,nextcol设置为下一个空位的坐标
//如果没有下一个空位,nextrow==9表示没有下一个空白位
if (j == (board.size() * board[0].size())) {
nextrow = 9;
nextcol = 0;
}
cout << "row = " << row << " col = " << col << endl;
cout << "nextrow = " << nextrow << " nextcol = " << nextcol << endl;
for (int i = 1; i <= 9; i++) {
flag = true;
cout << "Try to put " << i << " in row" << row << ", col" << col << endl;
if (!unique_in_row(board, row, col, i+'0'))
flag = false;
if (!unique_in_col(board, row, col, i+'0'))
flag = false;
if (!unique_in_square(board, row, col, i+'0'))
flag = false;
if (flag) {
cout << "Put " << i << " in row" << row << ", col" << col << endl;
board[row][col] = i+'0';
//两种情况合二为一:
//有下一个空白处,向下递归到nextrow, nextcol处
//没有下一个空白处 等价于 已经正确填写最后一个空白处 等价于 找到数独的解,向下递归的nextrow == 9,直接返回9
depth = helper(board, nextrow, nextcol);
//根据depth的值
if (depth == 9) {
return depth;
}
}
}
//board[row][col]中1到9都尝试了,行不通
//恢复为'.'返回上一出空白
cout << " 1~9 are all wrong in row" << row << ", col" << col << endl;
cout << "set row" << row << ", col" << col << " to be ." << endl;
board[row][col] = '.';
return row;
}
}
void solveSudoku(vector<vector<char>>& board) {
int first_empty_row, first_empty_col;
for (int i = 0; i < (board.size() * board[0].size()); i++)
if (board[i / 9][i % 9] == '.') {
first_empty_row = i / 9;
first_empty_col = i % 9;
break;
}
cout << first_empty_row << ", " << first_empty_col << endl;
//helper(board, first_empty_row, first_empty_col);
helper(board, first_empty_row, first_empty_col);
}
bool isValidSudoku(vector<vector<char>>& board) {
int n = board.size();
//cout << n << endl;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cout << i << ", " << j << endl;
if (board[i][j] == '.')
continue;
if (!unique_in_row(board, i, j, board[i][j])) {
cout << i << ", " << j << ", " << board[i][j];
return false;
}
if (!unique_in_col(board, i, j, board[i][j])){
cout << i << ", " << j << ", " << board[i][j];
return false;
}
if (!unique_in_square(board, i, j, board[i][j])){
cout << i << ", " << j << ", " << board[i][j] << endl;
return false;
}
}
}
return true;
}
int main()
{
/*"5"是const string 不能初始化char
vector<vector<char> > board1 = {
{"5","3",".",".","7",".",".",".","."},
{"6",".",".","1","9","5",".",".","."},
{".","9","8",".",".",".",".","6","."},
{"8",".",".",".","6",".",".",".","3"},
{"4",".",".","8",".","3",".",".","1"},
{"7",".",".",".","2",".",".",".","6"},
{".","6",".",".",".",".","2","8","."},
{".",".",".","4","1","9",".",".","5"},
{".",".",".",".","8",".",".","7","9"},
};
*/
vector<vector<char> > board1 = {
{'.', '8', '7', '6', '5', '4', '3', '2', '1'},
{'2', '.', '.', '.', '.', '.', '.', '.', '.'},
{'3', '.', '.', '.', '.', '.', '.', '.', '.'},
{'4', '.', '.', '.', '.', '.', '.', '.', '.'},
{'5', '.', '.', '.', '.', '.', '.', '.', '.'},
{'6', '.', '.', '.', '.', '.', '.', '.', '.'},
{'7', '.', '.', '.', '.', '.', '.', '.', '.'},
{'8', '.', '.', '.', '.', '.', '.', '.', '.'},
{'9', '.', '.', '.', '.', '.', '.', '.', '.'}};
vector<vector<char> > board = {
{'5','3','.', '.','7','.', '.', '.', '.'},
{'6','.', '.','1','9','5','.', '.','.'},
{'.','9','8','.', '.','.', '.','6','.'},
{'8','.', '.','.','6','.', '.','.','3'},
{'4','.', '.','8','.','3','.', '.','1'},
{'7','.', '.','.','2','.', '.','.','6'},
{'.','6','.', '.','.', '.','2','8','.'},
{'.', '.','.','4','1','9','.', '.','5'},
{'.', '.','.', '.','8','.', '.','7','9'},
};
setOrigin(board);
solveSudoku(board);
//bool real = isValidSudoku(board);
//cout << real << endl;
for (int i = 0; i <= 8; i++) {
for (int j = 0; j <= 8; j++) {
if (j == 0)
cout << "\n";
cout << board[i][j];
}
}
cout << "\n";
return 0;
}