//naked subset column int rule9( struct Sudoku* sud, unsigned int x, unsigned int y ) { unsigned int i, changed, subset, ctPartners; unsigned int partners[5]; for( subset = 5; subset >= 3; subset-- ) { if( __popcnt64( sud->grid[y][x] ) > subset ) continue; if( __popcnt64( sud->contains[CONTAINS_COL][y] ) < subset ) continue; ctPartners = 0; for( i = 0; i < sud->length; i++ ) { if( ( i != y ) && ( sud->grid[i][x] & sud->grid[y][x] ) && ( ( sud->grid[i][x] & ( ~sud->grid[y][x] ) ) == 0 ) ) { partners[ctPartners++] = i; } } if( ctPartners != subset ) continue; changed = 0; for( i = 0; i < sud->length; i++ ) { changed |= ( sud->grid[i][x] & ( ~sud->grid[y][x] ) ); sud->grid[i][x] &= ( ~sud->grid[y][x] ); } return changed; } return 0; }
//naked subset row int rule11( struct Sudoku* sud, unsigned int x, unsigned int y ) { struct Combinator c; SudokuCell cellok; SudokuCell subset; SudokuCell changed; unsigned int i, j, k; unsigned int index[64] = { 0 }; unsigned int combination[5] = { 0 }; j = 0; for( i = 0; i < sud->length; i++ ) { if( sud->cellvalue[y][i] == 0 && i != x ) { index[j++] = i; } } if( j <= 3 ) return 0; for( i = 2; i < 4; i++ ) { Combinator_Initialize( &c, i, index, j ); combination[i] = x; while( Combinator_GetNext( &c, combination ) == 0 ) { subset = 0; for( j = 0; j <= i; j++ ) { subset |= sud->grid[y][combination[j]]; for( k = j + 1; k <= i; k++ ) { if( sud->grid[y][combination[j]] & sud->grid[y][combination[k]] ) { cellok |= ( ( 1 << j ) | ( 1 << k ) ); break; } } } if( __popcnt64( cellok ) != i + 1 ) continue; if( __popcnt64( subset ) != i + 1 ) continue; changed = 0; for( j = 0; j < sud->length; j++ ) { if( ( cellok & ( 1ll << j ) ) == 0 ) { changed |= ( sud->grid[y][j] & subset ); sud->grid[y][j] &= ( ~subset ); } } return changed != 0; } } return 0; }
int strategy5( struct Sudoku* sud, unsigned int x, unsigned int y ) { unsigned int i, j; SudokuCell changed; //if cell contains more than 2 its not naked pair if( __popcnt64( sud->grid[y][x] ) != 2 ) return 0; for( i = 0; i < sud->length; i++ ) { if( i == y ) continue; //find identical partner if( sud->grid[i][x] == sud->grid[y][x] ) { changed = 0; for( j = 0; j < sud->length; j++ ) { //delete candidates from all other cells in neighbourhood if( j != i && j != y ) { changed |= ( sud->grid[j][x] & sud->grid[y][x] ); sud->grid[j][x] &= ( ~( sud->grid[y][x] ) ); } } return changed != 0; } } return 0; }
int BitCount(ulong mask) { #if X64POPCOUNT return (int)__popcnt64(mask); #else int count = 0; while (mask != 0) { count++; mask &= mask - 1; } return count; #endif }
//Hidden pairs in Reihen int rule7( struct Sudoku* sud, unsigned int x, unsigned int y ) { unsigned int i, j; SudokuCell candidate, neighbourhood; for( i = 0; i < sud->length; i++ ) { candidate = ( sud->grid[y][x] ) & ( sud->grid[y][i] ); if( __popcnt64( candidate ) == 2ll && i != x ) { if( ( __popcnt64( sud->grid[y][x] ) != 2ll ) || ( __popcnt64( sud->grid[y][i] ) != 2ll ) ) { neighbourhood = 0; for( j = 0; j < sud->length; j++ ) { if( j != i && j != x ) neighbourhood |= sud->grid[y][j]; } if( ( candidate & neighbourhood ) == 0 ) { sud->grid[y][i] = candidate; sud->grid[y][x] = candidate; return 1; } } return 0; } } return 0; }
//Naked pairs box int rule6( struct Sudoku* sud, unsigned int x, unsigned int y ) { unsigned int i, j; SudokuCell changed; if( __popcnt64( sud->grid[y][x] ) != 2 ) return 0; for( i = 0; i < sud->length; i++ ) { if( ( ( sud->grid[y][x] ) == ( *sud->cellbox[y][x][i] ) ) && ( &sud->grid[y][x] ) != sud->cellbox[y][x][i] ) { changed = 0; for( j = 0; j < sud->length; j++ ) { if( (j != i) && (sud->cellbox[y][x][j] != &sud->grid[y][x])) { changed |= ( ( *sud->cellbox[y][x][j] ) & sud->grid[y][x] ); *sud->cellbox[y][x][j] &= ( ~( sud->grid[y][x] ) ); } } return changed != 0; } } return 0; }
Size countBits(Size a) { #ifdef __GNUC__ #ifdef __X64__ return __builtin_popcountl(a); #else return __builtin_popcount(a); #endif #elif defined(_MSC_VER) #ifdef __X64__ return __popcnt64(a); #else return __popcnt(a); #endif #else //Very naive implementation. Size c = 0; while(a) { if(a & 1) c++; a >>= 1; } return c; #endif }
//:/ int rule15( struct Sudoku* sud, unsigned int x, unsigned int y ) { struct Combinator c; SudokuCell cellok; SudokuCell subset; SudokuCell changed; unsigned int i, j, k; unsigned int index[64] = { 0 }; unsigned int combination[5] = { 0 }; unsigned int curcell = BOXINDEX( sud, x, y ); j = 0; for( i = 0; i < sud->length; i++ ) { if( *sud->cellboxvalue[y][x][i] == 0 && i != curcell ) { index[j++] = i; } } if( j <= 3 ) return 0; for( i = 2; i < 4; i++ ) { Combinator_Initialize( &c, i, index, j ); combination[i] = curcell; while( Combinator_GetNext( &c, combination ) == 0 ) { subset = 0ll; for( j = 0; j <= i; j++ ) { for( k = j + 1; k <= i; k++ ) { if( *sud->cellbox[y][x][combination[j]] & *sud->cellbox[y][x][combination[k]] ) { cellok |= ( ( 1 << j ) | ( 1 << k ) ); subset |= *sud->cellbox[y][x][combination[j]] & *sud->cellbox[y][x][combination[k]]; break; } } } if( __popcnt64( cellok ) != i + 1 ) continue; for( j = 0; j < sud->length; j++ ) { if( ( cellok & ( 1ll << j ) ) == 0 ) subset &= ( ~( *sud->cellbox[y][x][j] ) ); } if( __popcnt64( subset ) != i + 1 ) continue; changed = 0; for( j = 0; j < sud->length; j++ ) { if( ( subset & ( 1ll << j ) ) != 0 ) { changed |= ( *sud->cellbox[y][x][j] & ( ~( subset ) ) ); *sud->cellbox[y][x][j] &= subset; } } return changed != 0; } } return 0; }
static inline int popcnt(std::uint64_t n) { return __popcnt64(n); }
int strategy14( struct Sudoku* sud, unsigned int x, unsigned int y ) { struct Combinator c; SudokuCell cellok; SudokuCell subset; SudokuCell changed; unsigned int i, j, k; unsigned int index[64] = { 0 }; unsigned int combination[5] = { 0 }; j = 0; //count number of empty cells in neighbourhood for( i = 0; i < sud->length; i++ ) { if( sud->cellvalue[x][i] == 0 && i != x ) { index[j++] = i; } } if( j <= SUDOKU_SUBSET_MIN ) return 0; //for defined subset sizes for( i = SUDOKU_SUBSET_MIN; i <= SUDOKU_SUBSET_MAX; i++ ) { Combinator_Initialize( &c, i, index, j ); combination[i] = x; //for each available combination while( Combinator_GetNext( &c, combination ) == 0 ) { subset = 0ll; for( j = 0; j <= i; j++ ) { for( k = j + 1; k <= i; k++ ) { //combine all subsets //create validation mask if( sud->grid[y][combination[j]] & sud->grid[y][combination[k]] ) { cellok |= ( ( 1 << j ) | ( 1 << k ) ); subset |= sud->grid[y][combination[j]] & sud->grid[y][combination[k]]; break; } } } //validate subset if( __popcnt64( cellok ) != i + 1 ) continue; for( j = 0; j < sud->length; j++ ) { if( ( cellok & ( 1ll << j ) ) == 0 ) subset &= ( ~( sud->grid[y][j] ) ); } if( __popcnt64( subset ) != i + 1 ) continue; //remove other candidates from cells in subset changed = 0; for( j = 0; j < sud->length; j++ ) { if( ( subset & ( 1ll << j ) ) != 0 ) { changed |= ( sud->grid[y][j] & ( ~( subset ) ) ); sud->grid[y][j] &= subset; } } return changed != 0; } } return 0; }