Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

About this user

Alexandru Scvortov

« Newer Snippets
Older Snippets »
Showing 1-1 of 1 total  RSS 

Sudoku Solver in C++

This is a complete implementation of a Sudoku solving programme. It reads a 9x9 matrix of ints from a text file (specified in main), and prints the completed board to stdout.

The input file should look like:
BEGIN sudoku.in
5 3 0 0 7 0 0 0 0
6 0 0 1 9 5 0 0 0
0 9 8 0 0 0 0 6 0
8 0 0 0 6 0 0 0 3
4 0 0 8 0 3 0 0 1
7 0 0 0 2 0 0 0 6
0 6 0 0 0 0 2 8 0
0 0 0 4 1 9 0 0 5
0 0 0 0 8 0 0 7 9
END sudoku.in

Full explanation: here

   1  
   2  #include <iostream>
   3  #include <fstream>
   4  
   5  using namespace std;
   6  
   7  class SudokuBoard;
   8  void printB(SudokuBoard sb);
   9  
  10  typedef unsigned int uint;
  11  
  12  const uint MAXVAL = 9;
  13  const uint L = 9;
  14  const uint C = 9;
  15  const uint S = L * C;
  16  const uint ZONEL = 3;
  17  const uint ZONEC = 3;
  18  const uint ZONES = ZONEL * ZONEC;
  19  
  20  const uint lineElements[L][C] = {
  21      { 0,  1,  2,  3,  4,  5,  6,  7,  8},
  22      { 9, 10, 11, 12, 13, 14, 15, 16, 17},
  23      {18, 19, 20, 21, 22, 23, 24, 25, 26},
  24      {27, 28, 29, 30, 31, 32, 33, 34, 35},
  25      {36, 37, 38, 39, 40, 41, 42, 43, 44},
  26      {45, 46, 47, 48, 49, 50, 51, 52, 53},
  27      {54, 55, 56, 57, 58, 59, 60, 61, 62},
  28      {63, 64, 65, 66, 67, 68, 68, 70, 71},
  29      {72, 73, 74, 75, 76, 77, 78, 79, 80}
  30  };
  31  
  32  const uint columnElements[C][L] = {
  33      { 0,  9, 18, 27, 36, 45, 54, 63, 72},
  34      { 1, 10, 19, 28, 37, 46, 55, 64, 73},
  35      { 2, 11, 20, 29, 38, 47, 56, 65, 74},
  36      { 3, 12, 21, 30, 39, 48, 57, 66, 75},
  37      { 4, 13, 22, 31, 40, 49, 58, 67, 76},
  38      { 5, 14, 23, 32, 41, 50, 59, 68, 77},
  39      { 6, 15, 24, 33, 42, 51, 60, 69, 78},
  40      { 7, 16, 25, 34, 43, 52, 61, 70, 79},
  41      { 8, 17, 26, 35, 44, 53, 62, 71, 80}
  42  };
  43  
  44  const uint zoneElements[S / ZONES][ZONES] = {
  45      { 0,  1,  2,  9, 10, 11, 18, 19, 20},
  46      { 3,  4,  5, 12, 13, 14, 21, 22, 23},
  47      { 6,  7,  8, 15, 16, 17, 24, 25, 26},
  48      {27, 28, 29, 36, 37, 38, 45, 46, 47},
  49      {30, 31, 32, 39, 40, 41, 48, 49, 50},
  50      {33, 34, 35, 42, 43, 44, 51, 52, 53},
  51      {54, 55, 56, 63, 64, 65, 72, 73, 74},
  52      {57, 58, 59, 66, 67, 68, 75, 76, 77},
  53      {60, 61, 62, 68, 70, 71, 78, 79, 80}
  54  };
  55  
  56  class SudokuBoard {
  57  public:
  58      SudokuBoard() :
  59          filledIn(0)
  60      {
  61          for (uint i(0); i < S; ++i)
  62              table[i] = usedDigits[i] = 0;
  63      }
  64  
  65      virtual ~SudokuBoard() {
  66      }
  67  
  68      int const at(uint l, uint c) { // Returns the value at line l and row c
  69          if (isValidPos(l, c))
  70              return table[l * L + c];
  71          else
  72              return -1;
  73      }
  74  
  75      void set(uint l, uint c, uint val) { // Sets the cell at line l and row c to hold the value val
  76          if (isValidPos(l, c) && ((0 < val) && (val <= MAXVAL))) {
  77              if (table[l * C + c] == 0)
  78                  ++filledIn;
  79              table[l * C + c] = val;
  80              for (uint i = 0; i < C; ++i) // Update lines
  81                  usedDigits[lineElements[l][i]] |= 1<<val;
  82              for (uint i = 0; i < L; ++i) // Update columns
  83                  usedDigits[columnElements[c][i]] |= 1<<val;
  84              int z = findZone(l * C + c);
  85              for (uint i = 0; i < ZONES; ++i) // Update columns
  86                  usedDigits[zoneElements[z][i]] |= 1<<val;
  87          }
  88      }
  89  
  90      void solve() {
  91          try { // This is just a speed boost
  92              scanAndSet(); // Logic approach
  93              goBruteForce(); // Brute force approach
  94          } catch (int e) { // This is just a speed boost
  95          }
  96      }
  97  
  98      void scanAndSet() {
  99          int b;
 100          bool changed(true);
 101          while (changed) {
 102              changed = false;
 103              for (uint i(0); i < S; ++i)
 104                  if (0 == table[i]) // Is there a digit already written?
 105                      if ((b = bitcount(usedDigits[i])) == MAXVAL - 1) { // If there's only one digit I can place in this cell, do
 106                          int d(1); // Find the digit
 107                          while ((usedDigits[i] & 1<<d) > 0)
 108                              ++d;
 109                          set(i / C, i % C, d); // Fill it in
 110                          changed = true; // The board has been changed so this step must be rerun
 111                      } else if (bitcount(usedDigits[i]) == MAXVAL)
 112                          throw 666; // Speed boost
 113          }
 114      }
 115  
 116      void goBruteForce() {
 117          int max(-1); // Find the cell with the _minimum_ number of posibilities (i.e. the one with the largest number of /used/ digits)
 118          for (uint i(0); i < S; ++i)
 119              if (table[i] == 0) // Is there a digit already written?
 120                  if ((max == -1) || (bitcount(usedDigits[i]) > bitcount(usedDigits[max])))
 121                      max = i;
 122  
 123          if (max != -1) {
 124              for (uint i(1); i <= MAXVAL; ++i) // Go through each possible digit
 125                  if ((usedDigits[max] & 1<<i) == 0) { // If it can be placed in this cell, do
 126                      SudokuBoard temp(*this); // Create a new board
 127                      temp.set(max / C, max % C, i); // Complete the attempt
 128                      temp.solve(); // Solve it
 129                      if (temp.getFilledIn() == S) { // If the board was completely solved (i.e. the number of filled in cells is S)
 130                          for (uint j(0); j < S; ++j) // Copy the board into this one
 131                              set(j / C, j % C, temp.at(j / C, j % C));
 132                          return; // Break the recursive cascade
 133                      }
 134                  }
 135          }
 136      }
 137  
 138      uint getFilledIn() {
 139          return filledIn;
 140      }
 141  
 142  private:
 143      uint table[S];
 144      uint usedDigits[S];
 145      uint filledIn;
 146  
 147      bool const inline isValidPos(int l, int c) {
 148          return ((0 <= l) && (l < (int)L) && (0 <= c) && (c < (int)C));
 149      }
 150  
 151      uint const inline findZone(uint off) {
 152          return ((off / C / ZONEL) * (C / ZONEC) + (off % C / ZONEC));
 153      }
 154  
 155      uint const inline bitcount(uint x) {
 156          uint count(0);
 157          for (; x; ++count, x &= (x - 1));
 158          return count;
 159      }
 160  };
 161  
 162  void printB(SudokuBoard sb) {
 163      cout << "  |  -------------------------------  |" << endl;
 164      for (uint i(0); i < S; ++i) {
 165          if (i % 3 == 0)
 166              cout << "  |";
 167          cout << "  " << sb.at(i / L, i % L);
 168          if (i % C == C - 1) {
 169              if (i / C % 3 == 2)
 170                  cout << "  |" << endl << "  |  -------------------------------";
 171              cout << "  |" << endl;
 172          }
 173      }
 174      cout << endl;
 175  }
 176  
 177  int main(int argc, char *argv[]) {
 178      SudokuBoard sb;
 179  
 180      ifstream fin("sudoku4.in");
 181      int aux;
 182      for (uint i(0); i < S; ++i) {
 183          fin >> aux;
 184          sb.set(i / L, i % L, aux);
 185      }
 186      fin.close();
 187  
 188      printB(sb);
 189      sb.solve();
 190      printB(sb);
 191  
 192      return 0;
 193  }
 194  
« Newer Snippets
Older Snippets »
Showing 1-1 of 1 total  RSS