Advertisement
framp

Sudoku Dancing Links Implementation

Jul 11th, 2011
539
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.73 KB | None | 0 0
  1. //Federico Rampazzo, 2011
  2. #include <iostream>
  3. #include <vector>
  4. #include <cstdlib>
  5. #include <ctime>
  6.  
  7. using namespace std;
  8.  
  9. class Sudoku{
  10.   private: // Dancing Links toroidal structures
  11.     class header;
  12.     class node{
  13.     public:
  14.       int row;
  15.       node * up, * down, * left, * right;
  16.       header * head;
  17.     };
  18.     class header : public node{
  19.     public:
  20.       int size;
  21.       bool visible;
  22.       header * left, * right;
  23.     };
  24.     int u, u2, u3, rowsNumber, columnsNumber, solutionsNumber, maxSolutionsNumber;
  25.     header * root;
  26.     vector<header> columns;
  27.     vector<vector<node> > rows;
  28.     vector<int> solutions;
  29.    
  30. public:
  31.   Sudoku(int dimension) :
  32.   u(dimension),
  33.   u2(u*u),
  34.   u3(u2*u2),
  35.   rowsNumber(u3*u2),
  36.   rows(rowsNumber, vector<node>(4, node())),
  37.   columnsNumber(u3*4+1),
  38.   columns(columnsNumber, header()),
  39.   solutions(u3, 0)
  40.   { // create the 729x324 matrix
  41.     root = &(columns[u3*4]);
  42.     for (int i = 0; i < columnsNumber; i++) {
  43.       columns[i].up = &(columns[i]);
  44.       columns[i].down = &(columns[i]);
  45.       columns[i].left = &(columns[(i+columnsNumber-1)%columnsNumber]);
  46.       columns[i].right = &(columns[(i+1)%columnsNumber]);
  47.       columns[i].visible = true;
  48.       columns[i].size = 0;
  49.     }
  50.     for (int i = 0; i < rowsNumber; i++) {
  51.       int r = i/(u3), c = i%u3/u2, p = i%u2;
  52.       for (int j = 0; j < 4; j++) {
  53.     int columnIndex;
  54.     // http://www.stolaf.edu/people/hansonr/sudoku/exactcover.htm
  55.     switch (j){
  56.       case 0: // cell constraints
  57.         columnIndex = u3*j + r*u2+c;
  58.         break;
  59.       case 1: //row constraints
  60.         columnIndex = u3*j + r*u2+p;
  61.         break;
  62.       case 2: //column constraints
  63.           columnIndex = u3*j + c*u2+p;
  64.           break;
  65.       case 3: //block constraints
  66.           columnIndex = u3*j + (r/u*u+c/u)*u2+p;
  67.           break;
  68.     }
  69.     rows[i][j].row = i;
  70.     rows[i][j].left = &(rows[i][(j+3)%4]);
  71.     rows[i][j].right = &(rows[i][(j+1)%4]);
  72.     rows[i][j].down = rows[i][j].head = &(columns[columnIndex]);
  73.     rows[i][j].up = columns[columnIndex].up;
  74.    
  75.     columns[columnIndex].up->down = columns[columnIndex].up = &(rows[i][j]);
  76.     columns[columnIndex].size++;
  77.       }
  78.     }
  79.   };
  80.  
  81.   void print(int * s){
  82.     for (int i=0; i<u3; i++){
  83.       if (i!=0 && i%(u*u2)==0){
  84.     cout << "\n";
  85.     for (int j=0; j<u; j++){
  86.       for (int k=0; k<u*2+2*((j==0 || j==u-1) ? 1 : 2); k++) cout << "-";
  87.       if (j!=u-1) cout << "+";
  88.     }
  89.       }
  90.       if      (i%u2==0) cout << "\n";
  91.       else if (i%u==0) cout << "  \u007C  ";
  92.      
  93.       cout << s[i]  << " ";
  94.     }
  95.     cout << "\n";
  96.   }
  97.  
  98.   int solver(int * grid, int max=1, bool fill=true){
  99.     int i = 0;
  100.     solutionsNumber = 0;
  101.     maxSolutionsNumber = max;
  102.     for (int j = 0; j<u3; j++){
  103.       if (grid[j]) {
  104.     int rowIndex = j*u2+grid[j]-1;
  105.     if (rows[rowIndex][0].head->visible==false ||
  106.       rows[rowIndex][1].head->visible==false ||
  107.       rows[rowIndex][2].head->visible==false ||
  108.       rows[rowIndex][3].head->visible==false) {
  109.       return -1; // unvalid puzzle
  110.       break;
  111.       }
  112.       for (int k = 0; k<4; k++)
  113.         cover(rows[rowIndex][k].head);
  114.       solutions[i++] = rowIndex;
  115.       }
  116.     }
  117.     backtrack(i);
  118.     if (solutionsNumber==0) return 0;
  119.     if (fill)
  120.       for (int j=0; j<u3; j++)
  121.     grid[solutions[j]/u2] = solutions[j]%u2+1;
  122.    
  123.     for (int j=i-1; j>=0; j--)
  124.       for (int k=3; k>=0; k--)
  125.     uncover(rows[solutions[j]][k].head);
  126.       return solutionsNumber;
  127.   }
  128.  
  129.   int generator (int * grid, int numbers=-1, int limit=1000, int randomness = 100){
  130.     for (int i=0; i<u3; i++)
  131.       grid[i] = 0;
  132.     solver(grid);
  133.    
  134.     srand((unsigned)time(0));
  135.     for (int i=0; i<randomness; i++){
  136.       int box = rand()%3, begin = rand()%3, end = rand()%3;
  137.       if (rand()%2==0){
  138.     for (int j=0; j<u2; j++){
  139.       int beginIndex = box*u2*u+begin*u2+j,
  140.           endIndex = box*u2*u+end*u2+j;
  141.       int t = grid[endIndex];
  142.       grid[endIndex] = grid[beginIndex];
  143.       grid[beginIndex] = t;
  144.     }
  145.       }else{
  146.     for (int j=0; j<u2; j++){
  147.       int beginIndex = box*u+j*u2+begin,
  148.           endIndex = box*u+j*u2+end;
  149.       int t = grid[endIndex];
  150.       grid[endIndex] = grid[beginIndex];
  151.       grid[beginIndex] = t;
  152.     }
  153.       }    
  154.     }
  155.    
  156.     if (numbers==-1) numbers = u3-u3/3;
  157.     for (int i=0; i<numbers; i++){
  158.       int t, r, c=0;
  159.       do{
  160.     if (c!=0) grid[r] = t;
  161.     r = rand()%u3;
  162.     t = grid[r];
  163.     grid[r] = 0;
  164.     if (++c>limit) break;
  165.       }while(solver(grid, 2, false)!=1);
  166.     }
  167.   }
  168.  
  169. private:
  170.   void cover(header *column){ // cover a column and its nodes' rows
  171.   column->visible = false;
  172.   column->right->left = column->left;
  173.   column->left->right = column->right;
  174.   for (node *i = column->down; i!=column; i=i->down){
  175.     for (node *j = i->right; j!=i; j=j->right) {
  176.       j->down->up = j->up;
  177.       j->up->down = j->down;
  178.       j->head->size--;
  179.     }
  180.   }
  181.   }
  182.  
  183.   void uncover(header *column){ // uncover a column and its nodes' rows
  184.   column->visible = true;
  185.   for (node *i = column->up; i!=column; i=i->up){
  186.     for (node *j = i->left; j!=i; j=j->left) {
  187.       j->head->size++;
  188.       j->up->down = j;
  189.       j->down->up = j;
  190.     }
  191.   }
  192.     column->left->right = column;
  193.   column->right->left = column;
  194.   }
  195.  
  196.   void backtrack(int i){
  197.     if (root->right == root) {
  198.       solutionsNumber++;
  199.       return;
  200.     }
  201.     header * column, * choosen = root->right;
  202.   for (column = root->right; column!=root; column=column->right) {
  203.     if (column->size < choosen->size)
  204.       choosen = column;
  205.     if (choosen->size==0) return;
  206.   }
  207.     cover(choosen);
  208.     for (node *row = choosen->down; row!=choosen && solutionsNumber<maxSolutionsNumber; row=row->down) {
  209.       if (solutionsNumber==0)
  210.     solutions[i] = row->row;
  211.       for (node *j = row->right; j!=row; j=j->right)
  212.     cover(j->head);
  213.       backtrack(i + 1);
  214.       for (node *j = row->left; j!=row; j=j->left)
  215.     uncover(j->head);
  216.     }
  217.     uncover(choosen);
  218.    
  219.   }
  220.  
  221. };
  222.  
  223.  
  224. int main(){
  225.   int empty[81] = {
  226.     0, 0, 0, 0,  0, 0,  0, 0, 0,
  227.     0, 0, 0, 0,  0, 0,  0, 0, 0,
  228.     0, 0, 0, 0,  0, 0,  0, 0, 0,
  229.     0, 0, 0, 0,  0, 0,  0, 0, 0,
  230.    
  231.     0, 0, 0, 0,  0, 0,  0, 0, 0,
  232.     0, 0, 0, 0,  0, 0,  0, 0, 0,
  233.    
  234.     0, 0, 0,  0, 0, 0,  0, 0, 0,
  235.     0, 0, 0,  0, 0, 0,  0, 0, 0,
  236.     0, 0, 0,  0, 0, 0,  0, 0, 0,
  237.   };
  238.   int minusthree[81] = {
  239.     0, 0, 0,  0, 0, 0,  0, 0, 0,
  240.     0, 2, 3,  0, 0, 0,  7, 8, 0,
  241.     1, 0, 0,  4, 0, 6,  0, 0, 9,
  242.    
  243.     9, 0, 0,  0, 5, 0,  0, 0, 4,
  244.     2, 0, 0,  0, 0, 0,  0, 0, 8,
  245.     0, 1, 0,  0, 0, 0,  0, 3, 0,
  246.    
  247.     0, 0, 8,  0, 0, 0,  3, 0, 0,
  248.     0, 0, 0,  2, 0, 9,  0, 0, 0,
  249.     0, 0, 0,  0, 1, 0,  0, 0, 0
  250.   };
  251.   int heart[81] = {
  252.     8, 7, 2,  0, 0, 9,  0, 0, 0,
  253.     0, 0, 0,  0, 3, 0,  4, 0, 0,
  254.     0, 0, 0,  0, 0, 1,  2, 0, 8,
  255.    
  256.     0, 0, 9,  0, 0, 0,  0, 8, 0,
  257.     3, 0, 7,  0, 0, 0,  6, 0, 5,
  258.     0, 2, 0,  0, 0, 0,  1, 0, 0,
  259.    
  260.     1, 0, 8,  2, 0, 0,  0, 0, 0,
  261.     0, 0, 5,  0, 9, 0,  0, 0, 0,
  262.     0, 0, 0,  1, 0, 0,  9, 5, 3
  263.   };
  264.  
  265.   clock_t begin, end;
  266.  
  267.   begin = clock();
  268.   Sudoku sudoku(3);
  269.  
  270.   cout << "Sudoku.solver\n";
  271.   sudoku.print(heart);
  272.   begin = clock();
  273.   cout << "Working.." << "\n";
  274.   int solutions = sudoku.solver(heart, 2);
  275.   end = clock();
  276.   sudoku.print(heart);
  277.   cout << solutions
  278.        << " solutions. Solved in " << ((double)(end - begin)*1000)/CLOCKS_PER_SEC << "\n";
  279.  
  280.  
  281.   cout << "\n\nSudoku.generator\n";
  282.   int mysudoku[81];
  283.   begin = clock();
  284.   cout << "Working.." << "\n";
  285.   sudoku.generator(mysudoku);
  286.   end = clock();
  287.   sudoku.print(mysudoku);
  288.   cout << "Generated in " << ((double)(end - begin)*1000)/CLOCKS_PER_SEC << "\n";
  289.  
  290.   begin = clock();
  291.   cout << "Working.." << "\n";
  292.   sudoku.solver(mysudoku);
  293.   end = clock();
  294.   sudoku.print(mysudoku);
  295.   cout << solutions
  296.        << " solutions. Solved in " << ((double)(end - begin)*1000)/CLOCKS_PER_SEC << "\n";
  297. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement