我正在尝试编写一个函数,该函数接收三位向量,表示从位置1-9的数独谜题的行,col和块中使用的数字。单元格只能使用未使用的数字,并且该函数应该返回所有向量中的数字是否强制一种可能性或是否存在多种可能性。我认为这意味着我必须合并所有三个向量,然后确定有哪些"未设置"结果模式中的位。
但是,我的函数在gdb中似乎没有返回正确的掩码,即使它受到这种派生的启发:http://graphics.stanford.edu/~seander/bithacks.html#MaskedMerge
我正在尝试合并两个中的一个集合,然后将第三个集合合并到上一个合并中,派生最终合并中的1个数量,并减去它以得出有多少个0。
然后,我写了以下函数:
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;
}
答案 0 :(得分:2)
根据这份文件:
http://www.cplusplus.com/doc/tutorial/variables/
短小不小于char。至少16位。 所以你可能错误地将零计算为32 - num_1s。
不是这样做,你可以得到一个无符号短路并用1填充它,在前9位设置0。
var = 0xFFFFFE00
通过这种方式,您可以避免解决方案在很大程度上取决于您使用的变量的大小。
该问题的解决方案可能是这个(假设上面的行,col和bloc):
possibilities = row | col | bloc;
while (possibilities != 0) {
num_0s += ((~possibilities)&1);
possibilities = (possibilities >> 1);
}
答案 1 :(得分:0)
如果我理解正确row
,col
和bloc
(sic)中的每一个都是位掩码,其中各个位(可能是位0-8)表示数字1的存在-9,你的面具是错的(而且确实毫无意义)。例如,如果col
设置了第8位,那么mask = (1 << col) - 1
将1向左移动256 - 因为unsigned short
极不可能超过256位宽,这导致0之后在您减去1之后,移位然后在掩码中设置所有位。此后(row & ~mask) | (col & mask)
将仅col
,因为~mask
为0。
我想到了几个简单的选择:
1)根本不要合并,只需分别对三个变量中的每个变量执行popcount。一些现代处理器有一个popcount指令,所以如果你管理使用它,例如通过编译器的内置函数(例如__builtin_popcount
),它甚至会更快。
2)单独屏蔽每个变量上的位并将它们移动到位置,例如:
const unsigned int mask = 0x1FF;
unsigned int final = (col & mask) | ((row & mask) << 9) | ((bloc & mask) << 18);
此外,不要从32减去1的数量,而是减去27(= 3×9)的数量 - 如果三个变量中的每一个都可以设置最多9位,那么这是1位的最大数量。
编辑:可能是因为我误解了你想通过合并做什么。如果你的意思是三个变量中所有1位的简单联合,那么它只是unsigned int final = col | row | bloc
而不需要掩码。然后你将从9中减去popcount(1位数)。