File indexing completed on 2024-04-28 04:04:44

0001 /****************************************************************************
0002  *    Copyright 2015  Ian Wadham <iandw.au@gmail.com>                       *
0003  *                                                                          *
0004  *    This program is free software; you can redistribute it and/or         *
0005  *    modify it under the terms of the GNU General Public License as        *
0006  *    published by the Free Software Foundation; either version 2 of        *
0007  *    the License, or (at your option) any later version.                   *
0008  *                                                                          *
0009  *    This program is distributed in the hope that it will be useful,       *
0010  *    but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0011  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0012  *    GNU General Public License for more details.                          *
0013  *                                                                          *
0014  *    You should have received a copy of the GNU General Public License     *
0015  *    along with this program.  If not, see <http://www.gnu.org/licenses/>. *
0016  ****************************************************************************/
0017 
0018 #include "dlxsolver.h"
0019 #include "ksudoku_logging.h"
0020 
0021 
0022 // #define DLX_LOG
0023 
0024 DLXSolver::DLXSolver (QObject * parent)
0025     :
0026     QObject       (parent),
0027     mBoardValues  (0),
0028     mSolutionMoves(nullptr),
0029     mGraph        (nullptr)
0030 {
0031 #ifdef DLX_LOG
0032     qCDebug(KSudokuLog) << "DLXSolver constructor entered";
0033 #endif
0034     mCorner = new DLXNode;
0035     clear();
0036 }
0037 
0038 DLXSolver::~DLXSolver()
0039 {
0040 #ifdef DLX_LOG
0041     qCDebug(KSudokuLog) << "DLXSolver destructor entered";
0042 #endif
0043     deleteAll();
0044     delete mCorner;
0045 }
0046 
0047 void DLXSolver::printDLX (bool forced)
0048 {
0049 #ifdef DLX_LOG
0050     bool verbose = (forced || (mGraph->order() <= 5));
0051 
0052     if ((mEndNodeNum < 0) || (mEndColNum < 0)) {
0053 
0054         qCDebug(KSudokuLog, "DLXSolver::printDLX(): EMPTY, mEndNodeNum %d, "
0055                 "mEndRowNum %d, mEndColNum %d",
0056                 mEndNodeNum, mEndRowNum, mEndColNum);
0057         return;
0058     }
0059     // fprintf (stderr, "\nDLX Matrix has %d cols, %d rows and %d ones\n\n",
0060                 // mEndColNum + 1, mEndRowNum + 1, mEndNodeNum + 1);
0061     DLXNode * colDLX = mCorner->right;
0062     if (colDLX == mCorner) {
0063         fprintf (stderr, "DLXSolver::printDLX(): ALL COLUMNS ARE HIDDEN\n");
0064         return;
0065     }
0066     int totGap  = 0;
0067     int nRows   = 0;
0068     int nNodes  = 0;
0069     int lastCol = -1;
0070     QList<DLXNode *> rowsRemaining;
0071     rowsRemaining.fill (0, mRows.count());
0072     if (verbose) fprintf (stderr, "\n");
0073     while (colDLX != mCorner) {
0074         int col = mColumns.indexOf(colDLX);
0075         if (verbose) fprintf (stderr, "Col %02d, %02d rows  ",
0076                               col, mColumns.at(col)->value);
0077         DLXNode * node = mColumns.at(col)->below;
0078         while (node != colDLX) {
0079             int rowNum = node->value;
0080             if (verbose) fprintf (stderr, "%02d ", rowNum);
0081             if (rowsRemaining.at (rowNum) == 0) {
0082                 nRows++;
0083             }
0084             rowsRemaining[rowNum] = mRows.at (rowNum);
0085             nNodes++;
0086             node = node->below;
0087         }
0088         int gap = col - (lastCol + 1);
0089         if (gap > 0) {
0090             if (verbose) fprintf (stderr, "covered %02d", gap);
0091             totGap = totGap + gap;
0092         }
0093         if (verbose) fprintf (stderr, "\n");
0094         colDLX = colDLX->right;
0095         lastCol = col;
0096     }
0097     if (verbose) fprintf (stderr, "\n");
0098     fprintf (stderr, "Matrix NOW has %d rows, %d columns and %d ones\n",
0099             nRows, lastCol + 1 - totGap, nNodes);
0100 #else
0101     Q_UNUSED (forced);
0102 #endif
0103 }
0104 
0105 void DLXSolver::recordSolution (const int solutionNum, QList<DLXNode *> & solution)
0106 {
0107     // Extract a puzzle solution from the DLX solver into mBoardValues. There
0108     // may be many solutions, found at various times as the solver proceeds.
0109 
0110     // TODO - DLXSolver's solutions are not needed for anything in KSudoku: we
0111     //        just need to know if there is more than 1 solution. In the future,
0112     //        maybe each solution could be returned via a signal-slot mechanism.
0113 
0114     int order = mGraph->order();
0115     int nCages = mGraph->cageCount();
0116     SudokuType t = mGraph->specificType();
0117     if (mSolutionMoves) {
0118     mSolutionMoves->clear();
0119     }
0120 #ifdef DLX_LOG
0121     qCDebug(KSudokuLog) << "NUMBER OF ROWS IN SOLUTION" << solution.size();
0122 #endif
0123     if ((t == Mathdoku) || (t == KillerSudoku)) {
0124     for (int n = 0; n < solution.size(); n++) {
0125         int rowNumDLX = solution.at (n)->value;
0126         int searchRow = 0;
0127 #ifdef DLX_LOG
0128         qCDebug(KSudokuLog) << "    Node" << n << "row number" << rowNumDLX;
0129 #endif
0130         for (int nCage = 0; nCage < nCages; nCage++) {
0131         int cageSize = mGraph->cage (nCage).size();
0132         int nCombos = (mPossibilitiesIndex->at (nCage + 1) -
0133                                mPossibilitiesIndex->at (nCage)) / cageSize;
0134         if ((searchRow + nCombos) <= rowNumDLX) {
0135             searchRow += nCombos;
0136             continue;
0137         }
0138         int comboNum = rowNumDLX - searchRow;
0139         int comboValues = mPossibilitiesIndex->at (nCage)
0140                                   + (comboNum * cageSize);
0141 #ifdef DLX_LOG
0142         qCDebug(KSudokuLog) << "Solution node" << n << "cage" << nCage
0143                          << mGraph->cage (nCage) << "combos" << nCombos;
0144         qCDebug(KSudokuLog) << "Search row" << searchRow << "DLX row" << rowNumDLX
0145                          << "cageSize" << cageSize << "combo" << comboNum
0146              << "values at" << comboValues;
0147 #endif
0148         const QList<int> cage = mGraph->cage (nCage);
0149         for (const int cell : cage) {
0150 #ifdef DLX_LOG
0151             fprintf (stderr, "%d:%d ", cell,
0152                 mPossibilities->at (comboValues));
0153 #endif
0154             // Record the sequence of cell-numbers, for use in hints.
0155             if (mSolutionMoves) {
0156             mSolutionMoves->append (cell);
0157             }
0158             mBoardValues [cell] = mPossibilities->at (comboValues);
0159             comboValues++;
0160         }
0161 #ifdef DLX_LOG
0162         fprintf (stderr, "\n\n");
0163 #endif
0164         break;
0165         }
0166     }
0167     }
0168     else {  // Sudoku or Roxdoku variant.
0169     for (DLXNode * node : std::as_const(solution)) {
0170         int rowNumDLX = node->value;
0171         mBoardValues [rowNumDLX/order] = (rowNumDLX % order) + 1;
0172     }
0173     }
0174 
0175 #ifdef DLX_LOG
0176     fprintf (stderr, "\nSOLUTION %d\n\n", solutionNum);
0177     printSudoku();
0178 #else
0179     Q_UNUSED (solutionNum);
0180 #endif
0181 }
0182 
0183 void DLXSolver::retrieveSolution (BoardContents & solution)
0184 {
0185     solution = mBoardValues;
0186 }
0187 
0188 void DLXSolver::printSudoku()
0189 {
0190     // TODO - The code at SudokuBoard::print() is VERY similar...
0191 #ifdef DLX_LOG
0192     // Used for test and debug, but the format is also parsable and loadable.
0193 
0194     char nLabels[] = "123456789";
0195     char aLabels[] = "abcdefghijklmnopqrstuvwxy";
0196     int index, value;
0197     int order     = mGraph->order();
0198     int blockSize = mGraph->base();
0199     int sizeX     = mGraph->sizeX();
0200     int sizeY     = mGraph->sizeY();
0201     int sizeZ     = mGraph->sizeZ();    // If 2-D, depth == 1, else depth > 1.
0202 
0203     for (int k = 0; k < sizeZ; k++) {
0204       int z = (sizeZ > 1) ? (sizeZ - k - 1) : k;
0205       for (int j = 0; j < sizeY; j++) {
0206         if ((j != 0) && (j % blockSize == 0)) {
0207             fprintf (stderr, "\n"); // Gap between square blocks.
0208         }
0209         int y = (sizeZ > 1) ? (sizeY - j - 1) : j;
0210         for (int x = 0; x < sizeX; x++) {
0211             index = mGraph->cellIndex (x, y, z);
0212             value = mBoardValues.at (index);
0213             if (x % blockSize == 0) {
0214                 fprintf (stderr, "  "); // Gap between square blocks.
0215             }
0216             if (value == UNUSABLE) {
0217                 fprintf (stderr, " '"); // Unused cell (e.g. in Samurai).
0218             }
0219             else if (value == VACANT) {
0220                 fprintf (stderr, " -"); // Empty cell (to be solved).
0221             }
0222             else {
0223                 value--;
0224                 char label = (order > 9) ? aLabels[value] : nLabels[value];
0225                 fprintf (stderr, " %c", label); // Given cell (or clue).
0226             }
0227         }
0228         fprintf (stderr, "\n");     // End of row.
0229       }
0230       fprintf (stderr, "\n");       // Next Z or end of 2D puzzle/solution.
0231     }
0232 #endif
0233 }
0234 
0235 int DLXSolver::solveSudoku (SKGraph * graph, const BoardContents & boardValues,
0236                                                int solutionLimit)
0237 {
0238     // NOTE: This procedure is not actually used in KSudoku, but was used to
0239     //       develop and test solveDLX(), using Sudoku and Roxdoku puzzles. It
0240     //       turned out that solveSudoku(), using DLX, was not significantly
0241     //       faster than the methods in the SudokuBoard class and had the
0242     //       disadvantage that no method to assess puzzle difficulty could
0243     //       be found for solveDLX().
0244 
0245     mBoardValues     = boardValues; // Used later for filling in a solution.
0246     mGraph           = graph;
0247 
0248     int nSolutions   = 0;
0249     int order        = graph->order();
0250     int boardArea    = graph->size();
0251     int nGroups      = graph->cliqueCount();
0252     int vacant       = VACANT;
0253     int unusable     = UNUSABLE;
0254 
0255 #ifdef DLX_LOG
0256     qCDebug(KSudokuLog) << "TEST for DLXSolver";
0257     printSudoku();
0258 
0259     qCDebug(KSudokuLog) << "DLXSolver::solve: Order" << order << "boardArea" << boardArea
0260              << "nGroups" << nGroups;
0261 #endif
0262 
0263     // Generate a DLX matrix for an empty Sudoku grid of the required type.
0264     // It has (boardArea*order) rows and (boardArea + nGroups*order) columns.
0265     clear();                // Empty the DLX matrix.
0266     mColumns.clear();
0267     mRows.clear();
0268     for (int n = 0; n < (boardArea + nGroups*order); n++) {
0269         mColumns.append (mCorner);
0270     }
0271     for (int n = 0; n < (boardArea*order); n++) {
0272         mRows.append (mCorner);
0273     }
0274 
0275     // Exclude constraints for unusable cells and already-filled cells (clues).
0276     for (int index = 0; index < boardArea; index++) {
0277         if (boardValues.at(index) != vacant) {
0278 #ifdef DLX_LOG
0279             qCDebug(KSudokuLog) << "EXCLUDE CONSTRAINT for cell" << index
0280                      << "value" << boardValues.at(index);
0281 #endif
0282             mColumns[index] = nullptr;
0283             for (int n = 0; n < order; n++) {
0284                 mRows[index*order + n] = nullptr;       // Drop row.
0285             }
0286             if (boardValues.at(index) == unusable) {
0287                 continue;
0288             }
0289             // Get a list of groups (row, column, etc.) that contain this cell.
0290             const QList<int> groups = graph->cliqueList (index);
0291 #ifdef DLX_LOG
0292             int row    = graph->cellPosY (index);
0293             int col    = graph->cellPosX (index);
0294             qCDebug(KSudokuLog) << "CLUE AT INDEX" << index
0295                      << "value" << boardValues.at(index)
0296                      << "row" << row << "col" << col << "groups" << groups;
0297 #endif
0298             int val = boardValues.at(index) - 1;
0299             for (const int group : groups) {
0300 #ifdef DLX_LOG
0301                 qCDebug(KSudokuLog) << "EXCLUDE CONSTRAINT" << (boardArea+group*order+val);
0302 #endif
0303                 mColumns[boardArea + group*order + val] = nullptr;
0304                 const QList<int> clique = graph->clique (group);
0305                 for (const int cell : clique) {
0306                     mRows[cell*order + val] = nullptr;  // Drop row.
0307                 }
0308             }
0309         }
0310     }
0311 
0312     // Create the initial set of columns.
0313     for (DLXNode * colDLX : std::as_const(mColumns)) {
0314         mEndColNum++;
0315         // If the constraint is not excluded, put an empty column in the matrix.
0316         if (colDLX != nullptr) {
0317             DLXNode * node = allocNode();
0318             mColumns[mEndColNum] = node;
0319             initNode (node);
0320             addAtRight (node, mCorner);
0321         }
0322     }
0323 
0324     // Generate the initial DLX matrix.
0325     int rowNumDLX = 0;
0326     for (int index = 0; index < boardArea; index++) {
0327         // Get a list of groups (row, column, etc.) that contain this cell.
0328         const QList<int> groups = graph->cliqueList (index);
0329 #ifdef DLX_LOG
0330         int row    = graph->cellPosY (index);
0331         int col    = graph->cellPosX (index);
0332         qCDebug(KSudokuLog) << "    Index" << index << "row" << row << "col" << col
0333                  << "groups" << groups;
0334 #endif
0335 
0336         // Generate a row for each possible value of this cell in the Sudoku
0337         // grid, representing part of a possible solution. Each row must have
0338         // 1's in columns that correspond to a constraint on the cell and on the
0339         // value (in each group to which the cell belongs --- row, column, etc).
0340 
0341         for (int possValue = 0; possValue < order; possValue++) {
0342 #ifdef DLX_LOG
0343             QString s = (mRows.at (rowNumDLX) == 0) ? "DROPPED" : "OK";
0344             qCDebug(KSudokuLog) << "Row" << rowNumDLX << s;
0345 #endif
0346             if (mRows.at (rowNumDLX) != nullptr) {  // Skip already-excluded rows.
0347                 mRows[rowNumDLX] = nullptr;     // Re-initialise a "live" row.
0348                 addNode (rowNumDLX, index); // Mark cell fill-in constraint.
0349                 for (const int group : groups) {
0350                     // Mark possibly-satisfied constraints for row, column, etc.
0351                     addNode (rowNumDLX, boardArea + group*order + possValue);
0352                 }
0353             }
0354             rowNumDLX++;
0355         }
0356     }
0357 #ifdef DLX_LOG
0358     printDLX(true);
0359     qCDebug(KSudokuLog) << "Matrix MAX had " << mRows.count() << " rows, " << mColumns.count()
0360                         << " columns and " << ((boardArea + nGroups*order)*order) << " ones";
0361     qCDebug(KSudokuLog) << "CALL solveDLX(), solution limit" << solutionLimit;
0362 #endif
0363     // Solve the DLX-matrix equivalent of the Sudoku-style puzzle.
0364     nSolutions = solveDLX (solutionLimit);
0365 #ifdef DLX_LOG
0366     qCDebug(KSudokuLog) << "FOUND" << nSolutions << "solutions, limit" << solutionLimit;
0367 #endif
0368     return nSolutions;
0369 }
0370 
0371 int DLXSolver::solveMathdoku (SKGraph * graph, QList<int> * solutionMoves,
0372                               const QList<int> * possibilities,
0373                               const QList<int> * possibilitiesIndex,
0374                               int solutionLimit)
0375 {
0376     mSolutionMoves = solutionMoves;
0377 #ifdef DLX_LOG
0378     qCDebug(KSudokuLog) << "DLXSolver::solveMathdoku ENTERED" << possibilities->size()
0379              << "possibilities" << possibilitiesIndex->size() << "index size";
0380 #endif
0381     int nSolutions   = 0;
0382     int order        = graph->order();
0383     int nCages       = graph->cageCount();
0384     int nGroups      = graph->cliqueCount();
0385 
0386     // Save these pointers for use later, in recordSolution().
0387     mGraph = graph;
0388     mPossibilities = possibilities;
0389     mPossibilitiesIndex = possibilitiesIndex;
0390     mBoardValues.fill (0, order * order);
0391 
0392     // Create an empty DLX matrix.
0393     clear();
0394     mColumns.clear();
0395     mRows.clear();
0396 
0397     // Create the initial set of columns.
0398     for (int n = 0; n < (nCages + nGroups * order); n++) {
0399         mEndColNum++;
0400         // Put an empty column in the matrix.
0401     DLXNode * node = allocNode();
0402     mColumns.append (node);
0403     initNode (node);
0404     addAtRight (node, mCorner);
0405     }
0406 
0407     int rowNumDLX = 0;
0408     int counter = 0;
0409     for (int n = 0; n < nCages; n++) {
0410     int size = graph->cage (n).size();
0411     int nVals = possibilitiesIndex->at (n + 1) - possibilitiesIndex->at (n);
0412     int nCombos = nVals / size;
0413     int index = possibilitiesIndex->at (n);
0414 #ifdef DLX_LOG
0415     qCDebug(KSudokuLog) << "CAGE" << n << "of" << nCages << "size" << size
0416                  << "nCombos" << nCombos << "nVals" << nVals
0417          << "index" << index << "of" << possibilities->size();
0418 #endif
0419     for (int nCombo = 0; nCombo < nCombos; nCombo++) {
0420         mRows.append (nullptr);     // Start a row for each combo.
0421         addNode (rowNumDLX, n); // Mark the cage's fill-in constraint.
0422         counter++;
0423 #ifdef DLX_LOG
0424         qCDebug(KSudokuLog) << "Add cage-node: row" << rowNumDLX << "cage" << n
0425                      << graph->cage (n);
0426 #endif
0427         const QList<int> cage = graph->cage (n);
0428         for (const int cell : cage ) {
0429         int possVal = possibilities->at (index);
0430         // qCDebug(KSudokuLog) << "    Cell" << cell << "possVal" << possVal;
0431         const QList<int> cliqueList = graph->cliqueList (cell);
0432         for (const int group : cliqueList) {
0433             // Poss values go from 0 to (order - 1) in DLX (so -1 here).
0434             addNode (rowNumDLX, nCages + group * order + possVal - 1);
0435             counter++;
0436         }
0437         index++;
0438         }
0439         rowNumDLX++;
0440     }
0441     }
0442     qCDebug(KSudokuLog) << "DLX MATRIX HAS" << mColumns.size() << "cols" << mRows.size() << "rows" << counter << "nodes";
0443     nSolutions = solveDLX (solutionLimit);
0444     return nSolutions;
0445 }
0446 
0447 /* TODO - Delete this eventually.
0448 void DLXSolver::testDLX ()
0449 {
0450     const int test [6][7] = {
0451         {1,0,0,1,0,0,1},
0452         {1,0,0,1,0,0,0},
0453         {0,0,0,1,1,0,1},
0454         {0,0,1,0,1,1,0},
0455         {0,1,1,0,0,1,1},
0456         {0,1,0,0,0,0,1}
0457     };
0458     const int w = 7;
0459     const int h = 6;
0460     fprintf (stderr, "\nTEST MATRIX\n");
0461     for (int row = 0; row < h; row++) {
0462         for (int col = 0; col < w; col++) {
0463             fprintf (stderr, " %d", test[row][col]);
0464         }
0465         fprintf (stderr, "\n");
0466     }
0467     fprintf (stderr, "\n");
0468     for (int row = 0; row < h; row++) {
0469         for (int col = 0; col < w; col++) {
0470             if (test[row][col]) addNode (row, col);
0471         }
0472     }
0473     printDLX();
0474     solveDLX (0);
0475 }
0476 */
0477 
0478 /*        HOW THE DANCING LINKS ALGORITHM WORKS IN METHOD solveDLX().
0479 
0480      The solution algorithm must satisfy every column's constraint if it is to
0481      succeed. So it proceeds by taking one column at a time and "covering" it.
0482      In this context, "covering" can mean logically hiding the column and so
0483      reducing the size of the matrix to be solved, as happens in the method
0484      coverColumn() below. But it also means that the constraint represented
0485      by that column is "covered" or satisfied, in the sense that a payment
0486      of money can be "covered" (i.e. provided for).
0487 
0488      Whichever column is covered first, one of its non-zero values must be in
0489      a row that is part of the solution, always supposing that there is a
0490      solution. Knuth recommends to select first the columns that have the
0491      smallest number of 1's. The algorithm then tries each column in turn and
0492      each non-zero item within that column, backtracking if there are no items
0493      left in a column. When all columns have been covered, a solution has been
0494      found, but the algorithm continues to search for other solutions until
0495      the caller's solution limit is reached. The solutions are delivered via
0496      the Qt library's signal-slot mechanism.
0497 
0498      The algorithm terminates when the first column in the next solution is to
0499      be chosen, but one of the columns has no 1's in it, meaning that there can
0500      be no further solution. In principle, this can happen right at the start,
0501      because the corresponding problem is insoluble, but more likely will be
0502      after an extensive search where the solution limit parameter is zero (no
0503      limit) or the number of solutions found is less than the required limit or
0504      there is no solution, even after an extensive search. The algorithm then
0505      returns the integer number of solutions found (possibly 0).
0506 
0507      The "Dancing Links" aspect of the algorithm refers to lists of nodes that
0508      are linked in four directions (left, right, above and below) to represent
0509      columns, rows and column headers. Each node represents a 1 in the matrix.
0510      Covering a column involves unlinking it from the columns on each side of
0511      it and unlinking each row that has a 1 in that column from the rows above
0512      and below. One of the nodes in the column is included (tentatively) in
0513      the current partial solution and so the other nodes and their rows cannot
0514      be. At the same time, the matrix reduces to a sub-matrix and sub-problem.
0515 
0516      The thing is that the removed columns and rows "remember" their previous
0517      state and can easily be re-linked if backtracking becomes necessary and
0518      they need to be "uncovered". Thus the nodes, links, columns and rows can
0519      "dance" in and out of the matrix as the solution proceeds. Furthermore,
0520      the algorithm can be written without using recursion. It just needs to
0521      keep a LIFO list (i.e. a stack) of nodes tentatively included in the
0522      current solution. Using iteration should make the algorithm go fast.
0523 */
0524 
0525 int DLXSolver::solveDLX (int solutionLimit)
0526 {
0527     int solutionCount  = 0;
0528     int level          = 0;
0529     DLXNode * currNode = nullptr;
0530     DLXNode * bestCol  = nullptr;
0531     QList<DLXNode *> solution;
0532     bool searching     = true;
0533     bool descending    = true;
0534 
0535     if (mCorner->right == mCorner) {
0536     // Empty matrix, nothing to solve.
0537         qCDebug(KSudokuLog) << "solveDLX(): EMPTY MATRIX, NOTHING TO SOLVE.";
0538         return solutionCount;
0539     }
0540 
0541     while (searching) {
0542         // Find the column with the least number of rows yet to be explored.
0543         int min = mCorner->right->value;
0544         bestCol = mCorner->right;
0545         for (DLXNode * p = mCorner->right; p != mCorner; p = p->right) {
0546             if (p->value < min) {
0547                 bestCol = p;
0548                 min = p->value;
0549             }
0550         }
0551 #ifdef DLX_LOG
0552         qCDebug(KSudokuLog) << "solveDLX: BEST COLUMN " << mColumns.indexOf(bestCol)
0553                             << " level " << level << " rows " << bestCol->value;
0554 #endif
0555 
0556         coverColumn (bestCol);
0557         currNode = bestCol->below;
0558         solution.append (currNode);
0559 #ifdef DLX_LOG
0560         fprintf (stderr, "CURRENT SOLUTION: %d rows:", solution.size());
0561         for (DLXNode * q : std::as_const(solution)) {
0562             fprintf (stderr, " %d", q->value);
0563         }
0564         fprintf (stderr, "\n");
0565 #endif
0566         while (descending) {
0567             if (currNode != bestCol) {
0568                 // Found a row: cover all other cols of currNode's row (L to R).
0569                 // Those constraints are satisfied (for now) by this row.
0570                 DLXNode * p = currNode->right;
0571                 while (p != currNode) {
0572                     coverColumn (p->columnHeader);
0573                     p = p->right;
0574                 }
0575                 // printDLX();
0576 
0577                 if (mCorner->right != mCorner) {
0578                     break;  // Start searching a new sub-matrix.
0579                 }
0580                 // All columns covered: a solution has been found.
0581                 solutionCount++;
0582                 recordSolution (solutionCount, solution);
0583                 if (solutionCount == solutionLimit) {
0584                     return solutionCount;
0585                 }
0586             }
0587             else {
0588                 // No more rows to try in this column.
0589                 uncoverColumn (bestCol);
0590                 if (level > 0) {
0591                     // Backtrack by one level.
0592                     solution.removeLast();
0593                     level--;
0594                     currNode = solution.at (level);
0595                     bestCol  = currNode->columnHeader;
0596 #ifdef DLX_LOG
0597                     qCDebug(KSudokuLog) << "BACKTRACKED TO LEVEL" << level;
0598 #endif
0599                 }
0600                 else {
0601                     // The search is complete.
0602                     return solutionCount;
0603                 }
0604             }
0605 
0606             // Uncover all other columns of currNode's row (R to L).
0607             // Restores those constraints to unsatisfied state in reverse order.
0608 #ifdef DLX_LOG
0609             qCDebug(KSudokuLog) << "RESTORE !!!";
0610 #endif
0611             DLXNode * p = currNode->left;
0612             while (p != currNode) {
0613                 uncoverColumn (p->columnHeader);
0614                 p = p->left;
0615             }
0616             // printDLX();
0617 
0618             // Select next row down and continue searching for a solution.
0619             currNode = currNode->below;
0620             solution [level] = currNode;
0621 #ifdef DLX_LOG
0622             qCDebug(KSudokuLog) << "SELECT ROW" << currNode->value
0623                      << "FROM COL" << mColumns.indexOf (currNode->columnHeader);
0624 #endif
0625         } // End while (descending)
0626 
0627         level++;
0628 
0629     } // End while (searching)
0630 
0631     return solutionCount;       // Should never reach this point.
0632 }
0633 
0634 void DLXSolver::coverColumn (DLXNode * colDLX)
0635 {
0636 #ifdef DLX_LOG
0637     fprintf (stderr, "coverColumn: %d rows %d\n",
0638              mColumns.indexOf(colDLX), colDLX->value); 
0639 #endif
0640     colDLX->left->right = colDLX->right;
0641     colDLX->right->left = colDLX->left;
0642 
0643     DLXNode * colNode = colDLX->below;
0644     while (colNode != colDLX) {
0645         DLXNode * rowNode = colNode->right;
0646 #ifdef DLX_LOG
0647         qCDebug(KSudokuLog) << "DLXSolver::coverColumn: remove DLX row" << rowNode->value;
0648 #endif
0649         while (rowNode != colNode) {
0650             rowNode->below->above = rowNode->above;
0651             rowNode->above->below = rowNode->below;
0652             rowNode->columnHeader->value--;
0653             rowNode = rowNode->right;
0654         }
0655         colNode        = colNode->below;
0656     }
0657 }
0658 
0659 void DLXSolver::uncoverColumn (DLXNode * colDLX)
0660 {
0661     DLXNode * colNode = colDLX->below;
0662     while (colNode != colDLX) {
0663         DLXNode * rowNode = colNode->right;
0664 #ifdef DLX_LOG
0665         qCDebug(KSudokuLog) << "DLXSolver::uncoverColumn: return DLX row"
0666                  << rowNode->value;
0667 #endif
0668         while (rowNode != colNode) {
0669             rowNode->below->above = rowNode;
0670             rowNode->above->below = rowNode;
0671             rowNode->columnHeader->value++;
0672             rowNode = rowNode->right;
0673         }
0674         colNode        = colNode->below;
0675     }
0676 
0677 #ifdef DLX_LOG
0678     fprintf (stderr, "uncoverColumn: %d rows %d\n",
0679              mColumns.indexOf(colDLX), colDLX->value); 
0680 #endif
0681     colDLX->left->right = colDLX;
0682     colDLX->right->left = colDLX;
0683 }
0684 
0685 void DLXSolver::clear()
0686 {
0687 #ifdef DLX_LOG
0688     qCDebug(KSudokuLog) << "=============================================================";
0689     qCDebug(KSudokuLog) << "DLXSolver::clear";
0690 #endif
0691     // Logically clear the DLX matrix, but leave all previous nodes allocated.
0692     // This is to support faster DLX solving on second and subsequent puzzles.
0693     mEndNodeNum  = -1;
0694     mEndRowNum   = -1;
0695     mEndColNum   = -1;
0696     initNode (mCorner);
0697 }
0698 
0699 void DLXSolver::addNode (int rowNum, int colNum)
0700 {
0701     DLXNode * header = mColumns.at (colNum);
0702     if (header == nullptr) {
0703         return;         // This constraint is excluded (clue or unused).
0704     }
0705 
0706     // Get a node from the pool --- or create one.
0707     DLXNode * node = allocNode();
0708 
0709     // Circularly link the node onto the end of the row.
0710     if (mRows.at (rowNum) == nullptr) {
0711         mRows[rowNum] = node;   // First in row.
0712         initNode (node);    // Linked to itself at left and right.
0713     }
0714     else {
0715         addAtRight (node, mRows.at (rowNum));
0716     }
0717 
0718     // Circularly link the node onto the end of the column.
0719     addBelow (node, header);
0720 
0721     // Set the node's data-values.
0722     node->columnHeader = header;
0723     node->value        = rowNum;
0724 
0725     // Increment the count of nodes in the column.
0726     header->value++;
0727 }
0728 
0729 DLXNode * DLXSolver::allocNode()
0730 {
0731     mEndNodeNum++;
0732     if (mEndNodeNum >= mNodes.count()) {
0733         // Allocate a node only when needed, otherwise re-use one.
0734         mNodes.append (new DLXNode);
0735     }
0736 
0737     return mNodes.at (mEndNodeNum);
0738 }
0739 
0740 void DLXSolver::initNode (DLXNode * node)
0741 {
0742     node->left = node->right = node;
0743     node->above = node->below = node;
0744     node->columnHeader = node;
0745     node->value = 0;
0746 }
0747 
0748 void DLXSolver::addAtRight (DLXNode * node, DLXNode * start)
0749 {
0750     node->right        = start;
0751     node->left         = start->left;
0752     start->left        = node;
0753     node->left->right  = node;
0754 }
0755 
0756 void DLXSolver::addBelow (DLXNode * node, DLXNode * start)
0757 {
0758     node->below        = start;
0759     node->above        = start->above;
0760     start->above       = node;
0761     node->above->below = node;
0762 }
0763 
0764 void DLXSolver::deleteAll()
0765 {
0766 #ifdef DLX_LOG
0767     qCDebug(KSudokuLog) << "DLXSolver::deleteAll() CALLED";
0768 #endif
0769     qDeleteAll (mNodes);    // Deallocate the nodes pointed to.
0770     mNodes.clear();
0771     mColumns.clear();       // Secondary pointers: no nodes to deallocate.
0772     mRows.clear();
0773 }
0774 
0775 #include "moc_dlxsolver.cpp"