按位运算和数字列表

Bitwise operation and list of numbers

我正在寻找一组小于或等于 128 (2^7) 的 8 个数字的列表,其中每对数字仅在 4 位位置不同。例如(较短的版本):考虑一组 4 个数字,考虑小于或等于 8 的数字,其不同的 2 位位置是 1、2、4、8。

更一般地说,是否有任何算法(伪代码)可以帮助我找到所需的 n 组(n 始终为偶数),每个组都小于 2^(n-1) 并且其中每一对数字恰好相差 n/2 位位置。我们可以假设 n<=64。

编辑:另外,告诉偶数的值它根本不存在。比如n=6,就没有这样的解。

一组8个小于128的数字,其中每对数字仅在4位位置不同,则为0、15、51、60、85、90、102、105。即:

00000000 (0)
00001111 (15)
00110011 (51)
00111100 (60)
01010101 (85)
01011010 (90)
01100110 (102)
01101001 (105)

我们以00000000 (0)为起点。

由于数字必须在 4 位位置不同,我们可以翻转最后 4 位以找到组中的下一个数字,00001111 (15)

要找到下一个数字,因为它必须与 0 和 15 相差 4 位,并且它们已经彼此相差 4 位,我们可以知道我们需要翻转前 4 位中的 2 位和下一个数字的最后 4 位中的 2 位。为了按升序查找数字,我们翻转第 3 位和第 4 位,并选择最后 4 位来匹配前 4 位。也就是说,位 1-4 现在是 0011,我们将位 5-8 设置为匹配,我们找到组中的下一个最小数字是 00110011 (51).

注意:我们任意设置第 5-8 位以匹配第 1-4 位,因为这是确保每个数字仍然与其他数字仅相差 4 位的最简单方法。数字的前半部分不会重复,除了一次我们翻转后半部分的所有位之外,因此后半部分也将始终与其他所有数字相差正确的位数。其他方法也应该有效,只要您能记住您已经使用过的模式并且不要重复它们。

同样,我们可以简单地翻转最后 4 位来找到组中的下一个数字,00111100 (60)

再次翻转每一半数字中的位,我们将位 1-4 设置为 0101 用于下一个最小数字,并将位 5-8 设置为匹配,用于 01010101 (85)

通过与上述相同的方法,我们可以找到该组中的其余数字为01011010 (90)01100110 (102)01101001 (105)

编辑: 查看数字的前半部分,我们选择前 4 位为 0000。然后,因为我们希望那一半数字中有 2 位不同,所以我们上升到 0011,然后是 0101,最后是 0110。这些数字中的每一个都是下一个最高的数字,只有两个位设置为 1。请注意,我们不能再高了,因为下一个数字将以 1001 开头,而 10010000 已经是 144,这高于 128 的给定限制。对于这些开始的每一半,我们还选择后半部分与第一部分相同的一个数字,然后翻转所有这些位作为第二个数字,找到两个数字每次我们找到一个可行的首发半场。

此方法也适用于更一般的情况,一次翻转 n/2 位。如果您想查找更大的数字组,您可能需要编写一个程序来为您执行这些操作。然而,我还没有机会彻底测试,但我相信这可能只适用于 n 是 2 的幂的情况。

编辑 2: 我正在考虑的另一种可能性是当 n 被 4 整除时它起作用。但是,上面使用的方法可能不太起作用并且需要调整。我在翻转适当数量的位数时遇到问题,同时确保每对数字仅相差正确的位数。

比如n=12,用上面的方法,我们找到的第一个数是:

000000000000 (0)
000000111111 (63)
000111000111 (455)
000111111000 (504)

Do not include:
001011001011 (715)  Differs from 455 by the incorrect number of bits
001011110100 (756)  Differs from 504 by the incorrect number of bits

问题是,我认为仅仅应用上述方法没有足够的组数。但是,如果您开始寻找在数字的每一半中位差不均匀的数字(例如,数字的前半部分有 2 位,后半部分有 4 位),则您可能能够找到足够的数字下半场),但我在寻找一种一致且可靠的方法来查找更多这些数字时遇到了问题,因为它们还必须与其他数字中的每个数字相差正确的位数。

@Allen Tsang,感谢您的编辑。明白了方法。基本上是递归。

对于 n=1 数字是 0

对于 n=2 数字是

00

01

对于 n=4 数字是

0000

0011

0101

0110

对于 n=8 数字是

00000000

00001111

00110011

00111100

01010101

01011010

01100110

01101001

即基本上复制前一个数字的 ans 以获得 (n/2) 组的初始数字。然后对于第一个,右边部分与左边相同,对于第二个,右边部分是第一个数字右边部分的补码。

非常感谢您的编辑。我得到了方法。

不过,只剩下一个疑问了。答案是否只适用于仅是 2 的幂的数字?我试过为此提交代码,但给出了错误的答案。