I further improved my implementation of the superset method by adding a fast check for (weak) minimality, so this might also be of interest out of this thread.
The idea is to check whether a clue is implied by the other clues via naked or hidden singles. This is easy to implement and it works wonders as you can see in the updated tables in my former
post, especially for larger subsets. Note that this does not suffice to validate whether a puzzle is minimal but it can be used to detect non-minimality.
So how good is it? I tested it on 500,000 random subsets of size 26 of which only 28,210 where minimal. Using just ZhouSolver it takes 18.98 seconds. But if I call "Simple MinCheck" before ZhouSolver the program only needs 6.95 seconds. The new algorithm identifies 398,655 non-minimal puzzles which equals about 84.5 % of all non-minimal subsets. Sadly the new algorithm has only little impact on the UA46 test and the main UA algorithm which is used to add clues for the superset method.
The following code uses tables from JSolve but it's hopefully easy enough to understand. Also the code is still under development, so there's room for improvement.
- Code: Select all
bool JClass ::
simpleMinCheck(int * num) {
int a, c, cell;
int mask;
CONST Cell * pC;
memset(board,0,sizeof(board));
memset(board2,0,sizeof(board2));
for (cell=0; cell<CELLS; cell++) if (num[cell]) {
mask = DigitToMask(num[cell]); //1 << (digit-1)
board[cell] |= mask; //Exception for clues to detect naked singles
board2[cell] = MaskAllDigits; //Exception for clues to detect hidden singles
pC = NeighborList(cell);
for (c=0; c<NEIGHBORS; c++) {
a = *pC++;
board2[a] |= (board[a] & mask); //Cell sees at least two clues with the same value
board[a] |= mask; //Candidate is not possible
}
}
//Hidden single
for (c=0; c<HOUSES; c++) { //Which candidates are not possible in each house?
mask = MaskAllDigits;
for (cell=0; cell<DIGITS; cell++) mask &= board2[HouseCellList(c,cell)];
if (mask) return false;
}
//Naked single
for (cell=0; cell<CELLS; cell++) if (board[cell] == MaskAllDigits) return false;
return true;
}
Edit: The algorithm can also detect invalid (as in having no solution) puzzles but not all of them.