给定A中的输入二进制数列表和B中的输出二进制数列表,为满足按位AND的所有X寻找一个值。即A和X = B,其中A具有6个设置位,B具有0到6个设置位,并且X具有12个设置位。 A,B和X中的所有数字都是128位长。
与此问题类似:Most efficient method of generating a random number with a fixed number of bits set 但是,当使用已知的二进制数字进行逐位编辑时,我还需要该随机数来生成已知的二进制结果。< / em>的
一个天真的想法:生成一个随机的128位数字X,设置为12位,然后针对A中的所有数字进行测试,看它是否生成B.如果没有,则将其洗牌X中的位,然后再试一次。
我知道必须有更好的算法。
澄清:B与A相同,除了A中的部分或全部位(1)已经在B中随机设置为0。
更新我天真的想法:
我只是想通了每当A中的一位为1时,相应的位就在 X将等于B中的对应位,因为1 AND xBit = bBit。 当A中的位为0时,则xBit未知(0或1)。所以每个人 在A中的数字,我可以获得由1,零和未知y组成的字符串X. 例如yy00011y10010y10 ...然后我可以比较所有这些字符串X到 通过用1代替y来找到唯一X的“拟合” 和0。我不确定这是不是最好的方法,但它可能是 比猜测和检查更好。有什么想法,或如何找到这样的合适?感谢
答案 0 :(得分:2)
您可以在Binary Decision Diagram中编码约束,从计算机编程艺术第4A卷(计算每个BDD节点的解决方案数量)应用算法C,然后从中生成随机解决方案。
对于每个节点,您可以选择“高”还是“低”,具体取决于您是选择该变量为1还是0.两种方式都有一些解决方案,我们称之为#H和#L。为了随机选择使得每个解决方案具有相同的可能性,选择高(即将此变量设置为1),概率为#H / (#H + #L)
,低选1减去该概率。继续这样做,直到你在汇聚节点。这通常会起作用,而不仅仅是这个问题。
BDD可以通过交叉构建(这个算法在TAOCP中给出但当然存在于每个BDD库中)一个编码A & X = B
约束的BDD(平凡 - 只是一个强制某些位不变的线性BDD)并且省略所有不受约束的比特),BDD强制X的popcnt为12(这看起来像一个12 x 128“网格”的节点,附加一些额外的链,每个附加的设置位都到达底部接收器)。我想总BDD也可以立即构建,而不是分两步,但这听起来有点烦人。
非随机解决方案也可以更直接地生成,首先放入最多6个必需位:
X = B // assuming A & B = B
然后把剩下的1个放在任何“无害”的地方,
R = (1 << (12 - popcnt(X))) - 1 // right number of 1's, wrong place
X |= _pdep_u64(R, ~A);
A没有约束的任何地方都可以,但是如果我们不关心随机性,那么这很好。另请注意,我使用的是_pdep_u64
,而不是像_pdep_u128
那样,但这没关系,因为低64位总是有空间可容纳12位,A只有6位,至少有58位为剩下的比特去。
答案 1 :(得分:1)
我刚刚找到了一个解决方案,进一步从我的 更新到上面的天真想法 。
将X字符串中的所有未知y值设置为0,然后按位或全部设置 X结果得到满足所有的X的最终值。
由于我只检查A中的6位,因此可以正常工作,但在另一种情况下这可能无法很好地扩展。
看起来很简单,我已经在很多套上进行了测试。它运作良好,但我不确定它是否是最佳方式。