0

I am trying to write a function which takes in three bit vectors representing the digits in use in the row, col and block of a Sudoku puzzle from positions 1-9. A cell can only use digits that are unused, and the function is supposed to return whether the digits in all the vectors force one possibility or whether there is more than one possibility. I took this to mean that I would have to merge all three vectors, and then determine where there were "unset" bits in the resulting pattern.

However, my function does not seem in gdb to be returning the correct mask even though it was inspired by this derivation: http://graphics.stanford.edu/~seander/bithacks.html#MaskedMerge

I am trying to merge one set among two, then the third set into the previous merge, derive the number of 1s in the final merge, and subtract it to derive how many 0s there are.

Then, I wrote the following function:

   bool possibilities(unsigned short row, unsigned short col, unsigned short bloc)
   {

    unsigned int mask = (1 << col) - 1;
    unsigned int inbw = (row & ~mask) | (col & mask);

    unsigned int mask2 = (1 << bloc) - 1;
    unsigned int final = (inbw & ~mask2) | (bloc & mask2);

    int num_1s;
    while (result != 0) {
            result &= (result - 1);
            num_1s++;
    }

    int zeroes = 32 - num_1s; // 32 being the presumed number of bits in a short.

    if (zeroes == 1) return true;
    return false;
   }
Valentin Mercier
  • 5,056
  • 3
  • 24
  • 49

2 Answers2

2

According to this document:

http://www.cplusplus.com/doc/tutorial/variables/

A short is not smaller than char. At least 16 bits. So you could be wrong calculating the zeroes as 32 - num_1s.

Instead of doing so, you can get an unsigned short and fill it with 1s, setting 0s at first 9 bits.

var = 0xFFFFFE00

By that way you avoid that the solution depends strongly on the size of the variable you use.

A solution to that problem could be this (assuming row, col and bloc like above):

possibilities = row | col | bloc;
while (possibilities != 0) {
     num_0s += ((~possibilities)&1);
     possibilities = (possibilities >> 1);
}
lilezek
  • 5,800
  • 19
  • 43
0

If I understood correctly that each of row, col, and bloc (sic) are bit masks with individual bits (presumably bits 0-8) representing the presence of digits 1-9, your masks are wrong (and indeed quite pointless). For example, if col has bit 8 set, then mask = (1 << col) - 1 shifts 1 to the left by 256 – since it is extremely unlikely that unsigned short be over 256 bits wide, this results in 0 after the shift and then in a mask with all bits set after you subtract the 1. After this (row & ~mask) | (col & mask) will be only col since ~mask is 0.

A couple of simple options come to mind:

1) Don't merge at all, simply do the popcount on each of the three variables individually. Some modern processors have an instruction for popcount, so if you manage use that, e.g., through a compiler's built-in function (e.g., __builtin_popcount), it will even be faster.

2) Mask the bits on each variable individually and shift them to position, e.g.:

const unsigned int mask = 0x1FF;
unsigned int final = (col & mask) | ((row & mask) << 9) | ((bloc & mask) << 18);

Also, don't subtract the number of 1's from 32 but from 27 (= 3×9) - that's the maximum number of 1 bits if each of the three variables can have at most 9 bits set.

Edit: Could be that I've misunderstood what you are trying to do by merging. If you mean a simple union of all 1 bits in the three variables, then it would be just unsigned int final = col | row | bloc with no need to mask. Then you would subtract the popcount (number of 1 bits) from 9.

Arkku
  • 37,604
  • 10
  • 57
  • 79
  • In the second option, why have you used 0x1FF as a mask? What do you mean by shifting these values into the right positions (e.g. 9)? –  Jul 21 '14 at 12:32
  • @marchon `0x1FF` is the mask with the lowest 9 bits set (`0b111111111`). By shifting to position I mean as shown, e.g., take bits 0-8 from `col`, 9-17 from `row`, and 18-26 from `bloc`. – Arkku Jul 21 '14 at 12:34