C++ Sudoku Dancing Links Implementation Program By Naim Hashmi
//Naim Hashmi, 2014
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
using namespace std;
class Sudoku{
private: // Dancing Links toroidal structures
class header;
class node{
public:
int row;
node * up, * down, * left, * right;
header * head;
};
class header : public node{
public:
int size;
bool visible;
header * left, * right;
};
int u, u2, u3, rowsNumber, columnsNumber, solutionsNumber, maxSolutionsNumber;
header * root;
vector<header> columns;
vector<vector<node> > rows;
vector<int> solutions;
public:
Sudoku(int dimension) :
u(dimension),
u2(u*u),
u3(u2*u2),
rowsNumber(u3*u2),
rows(rowsNumber, vector<node>(4, node())),
columnsNumber(u3*4+1),
columns(columnsNumber, header()),
solutions(u3, 0)
{ // create the 729x324 matrix
root = &(columns[u3*4]);
for (int i = 0; i < columnsNumber; i++) {
columns[i].up = &(columns[i]);
columns[i].down = &(columns[i]);
columns[i].left = &(columns[(i+columnsNumber-1)%columnsNumber]);
columns[i].right = &(columns[(i+1)%columnsNumber]);
columns[i].visible = true;
columns[i].size = 0;
}
for (int i = 0; i < rowsNumber; i++) {
int r = i/(u3), c = i%u3/u2, p = i%u2;
for (int j = 0; j < 4; j++) {
int columnIndex;
// http://www.stolaf.edu/people/hansonr/sudoku/exactcover.htm
switch (j){
case 0: // cell constraints
columnIndex = u3*j + r*u2+c;
break;
case 1: //row constraints
columnIndex = u3*j + r*u2+p;
break;
case 2: //column constraints
columnIndex = u3*j + c*u2+p;
break;
case 3: //block constraints
columnIndex = u3*j + (r/u*u+c/u)*u2+p;
break;
}
rows[i][j].row = i;
rows[i][j].left = &(rows[i][(j+3)%4]);
rows[i][j].right = &(rows[i][(j+1)%4]);
rows[i][j].down = rows[i][j].head = &(columns[columnIndex]);
rows[i][j].up = columns[columnIndex].up;
columns[columnIndex].up->down = columns[columnIndex].up = &(rows[i][j]);
columns[columnIndex].size++;
}
}
};
void print(int * s){
for (int i=0; i<u3; i++){
if (i!=0 && i%(u*u2)==0){
cout << "\n";
for (int j=0; j<u; j++){
for (int k=0; k<u*2+2*((j==0 || j==u-1) ? 1 : 2); k++) cout << "-";
if (j!=u-1) cout << "+";
}
}
if (i%u2==0) cout << "\n";
else if (i%u==0) cout << " \u007C ";
cout << s[i] << " ";
}
cout << "\n";
}
int solver(int * grid, int max=1, bool fill=true){
int i = 0;
solutionsNumber = 0;
maxSolutionsNumber = max;
for (int j = 0; j<u3; j++){
if (grid[j]) {
int rowIndex = j*u2+grid[j]-1;
if (rows[rowIndex][0].head->visible==false ||
rows[rowIndex][1].head->visible==false ||
rows[rowIndex][2].head->visible==false ||
rows[rowIndex][3].head->visible==false) {
return -1; // unvalid puzzle
break;
}
for (int k = 0; k<4; k++)
cover(rows[rowIndex][k].head);
solutions[i++] = rowIndex;
}
}
backtrack(i);
if (solutionsNumber==0) return 0;
if (fill)
for (int j=0; j<u3; j++)
grid[solutions[j]/u2] = solutions[j]%u2+1;
for (int j=i-1; j>=0; j--)
for (int k=3; k>=0; k--)
uncover(rows[solutions[j]][k].head);
return solutionsNumber;
}
int generator (int * grid, int numbers=-1, int limit=1000, int randomness = 100){
for (int i=0; i<u3; i++)
grid[i] = 0;
solver(grid);
srand((unsigned)time(0));
for (int i=0; i<randomness; i++){
int box = rand()%3, begin = rand()%3, end = rand()%3;
if (rand()%2==0){
for (int j=0; j<u2; j++){
int beginIndex = box*u2*u+begin*u2+j,
endIndex = box*u2*u+end*u2+j;
int t = grid[endIndex];
grid[endIndex] = grid[beginIndex];
grid[beginIndex] = t;
}
}else{
for (int j=0; j<u2; j++){
int beginIndex = box*u+j*u2+begin,
endIndex = box*u+j*u2+end;
int t = grid[endIndex];
grid[endIndex] = grid[beginIndex];
grid[beginIndex] = t;
}
}
}
if (numbers==-1) numbers = u3-u3/3;
for (int i=0; i<numbers; i++){
int t, r, c=0;
do{
if (c!=0) grid[r] = t;
r = rand()%u3;
t = grid[r];
grid[r] = 0;
if (++c>limit) break;
}while(solver(grid, 2, false)!=1);
}
}
private:
void cover(header *column){ // cover a column and its nodes' rows
column->visible = false;
column->right->left = column->left;
column->left->right = column->right;
for (node *i = column->down; i!=column; i=i->down){
for (node *j = i->right; j!=i; j=j->right) {
j->down->up = j->up;
j->up->down = j->down;
j->head->size--;
}
}
}
void uncover(header *column){ // uncover a column and its nodes' rows
column->visible = true;
for (node *i = column->up; i!=column; i=i->up){
for (node *j = i->left; j!=i; j=j->left) {
j->head->size++;
j->up->down = j;
j->down->up = j;
}
}
column->left->right = column;
column->right->left = column;
}
void backtrack(int i){
if (root->right == root) {
solutionsNumber++;
return;
}
header * column, * choosen = root->right;
for (column = root->right; column!=root; column=column->right) {
if (column->size < choosen->size)
choosen = column;
if (choosen->size==0) return;
}
cover(choosen);
for (node *row = choosen->down; row!=choosen && solutionsNumber<maxSolutionsNumber; row=row->down) {
if (solutionsNumber==0)
solutions[i] = row->row;
for (node *j = row->right; j!=row; j=j->right)
cover(j->head);
backtrack(i + 1);
for (node *j = row->left; j!=row; j=j->left)
uncover(j->head);
}
uncover(choosen);
}
};
int main(){
int empty[81] = {
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
};
int minusthree[81] = {
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 2, 3, 0, 0, 0, 7, 8, 0,
1, 0, 0, 4, 0, 6, 0, 0, 9,
9, 0, 0, 0, 5, 0, 0, 0, 4,
2, 0, 0, 0, 0, 0, 0, 0, 8,
0, 1, 0, 0, 0, 0, 0, 3, 0,
0, 0, 8, 0, 0, 0, 3, 0, 0,
0, 0, 0, 2, 0, 9, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0
};
int heart[81] = {
8, 7, 2, 0, 0, 9, 0, 0, 0,
0, 0, 0, 0, 3, 0, 4, 0, 0,
0, 0, 0, 0, 0, 1, 2, 0, 8,
0, 0, 9, 0, 0, 0, 0, 8, 0,
3, 0, 7, 0, 0, 0, 6, 0, 5,
0, 2, 0, 0, 0, 0, 1, 0, 0,
1, 0, 8, 2, 0, 0, 0, 0, 0,
0, 0, 5, 0, 9, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 9, 5, 3
};
clock_t begin, end;
begin = clock();
Sudoku sudoku(3);
cout << "Sudoku.solver\n";
sudoku.print(heart);
begin = clock();
cout << "Working.." << "\n";
int solutions = sudoku.solver(heart, 2);
end = clock();
sudoku.print(heart);
cout << solutions
<< " solutions. Solved in " << ((double)(end - begin)*1000)/CLOCKS_PER_SEC << "\n";
cout << "\n\nSudoku.generator\n";
int mysudoku[81];
begin = clock();
cout << "Working.." << "\n";
sudoku.generator(mysudoku);
end = clock();
sudoku.print(mysudoku);
cout << "Generated in " << ((double)(end - begin)*1000)/CLOCKS_PER_SEC << "\n";
begin = clock();
cout << "Working.." << "\n";
sudoku.solver(mysudoku);
end = clock();
sudoku.print(mysudoku);
cout << solutions
<< " solutions. Solved in " << ((double)(end - begin)*1000)/CLOCKS_PER_SEC << "\n";
}
1 comments:
LOL https://pastebin.com/9sntsqz6
If the answers is incorrect or not given, you can answer the above question in the comment box. If the answers is incorrect or not given, you can answer the above question in the comment box.