给定一个伪随机数生成器int64 rand64()
,我想构建一组伪随机数。此集应具有以下属性:每个子集的XOR组合不应导致值0。
我正在考虑以下算法:
count = 0
set = {}
while (count < desiredSetSize)
set[count] = rand64()
if propertyIsNotFullfilled(set[0] to set[count])
continue
count = count + 1
问题是:propertyIsNotFullfilled
如何实施?
注意:我想生成这样一个集合的原因如下:我有一个哈希表,其中哈希值是通过Zobrist hashing生成的。我没有为每个哈希表条目保留一个布尔值来指示条目是否已填充,而是认为哈希值(与每个条目一起存储)足以用于此信息(0 ...空,!= 0 ...设置)。将此信息作为标记值在散列键表中携带还有另一个原因。我正在尝试从AoS(结构阵列)切换到SoA(阵列结构)内存布局。我正在尝试这样做以避免填充并测试是否存在较少的缓存未命中。我希望在大多数情况下访问hash-key-table就足够了(暗示如果条目为空,哈希值提供信息)。
我还考虑过保留此信息的最重要的哈希值,但这会减少可能的哈希值的区域,而不是必要的。从理论上讲,该区域将从2 64 (减去传感器0值)减少到2 63 。
可以用另一种方式读取问题:给定一组84个伪随机数,是否有任何数字不能通过对该集合的任何子集进行异或运算来生成,以及如何获取它?这个数字可以用作哨兵值
现在,我需要它:我开发了一个连接四游戏引擎。玩家A和玩家B可以进行6 x 7次移动。因此有84种可能的移动(因此需要84个随机值)。通过预先计算的随机值以下列方式生成板状态的哈希值:hash(board) = randomset[move1] XOR randomset[move2] XOR randomset[move3] ...
答案 0 :(得分:4)
此集合应具有以下属性:每个子集的XOR组合不应产生值0。
恕我直言,这会将子集的最大数量限制为64(鸽笼原则);对于&gt; 64个子集,总会有一个(非空)子集,其异或为零。对于较小的子集,可以实现该属性。
进一步说明我的观点:考虑64个未知变量的64个方程组。然后,添加一个额外的等式。方程式和变量是布尔值的事实并没有使问题不同。
- EDIT / UPDATE--:由于应用程序似乎是游戏“connect-four”,您可以改为枚举所有可能的配置。无法对不可能的电路板配置进行编码将节省足够的编码空间,以适应64位的任何有效电路板位置:
将彩色宝石编码为{A,B},与{X}无关,(hight = 6)列的配置可以是以下之一:
X
X X
X X X
X X X X
X X X X X
_ A A A A A A <<-- possible configurations for one pile
--+--+--+--+--+--+--+
1 1 2 4 8 16 32 <<-- number of combinations of the Xs
-2 -5 <<-- number of impossible Xs
(类似于B代替A)。桩下面的数字是顶部Xs的可能性数量,负数是禁止/不可能配置的数量。对于具有一个A和4个X的列,X的每个值都是有效的,*除了3 * A(游戏已经结束)。对于最右边的桩也是一样的:底部的3X不能都是A,而X对于所有的X都不能是B.
这导致总共1 + 2 *(63-7):= 113。 (1表示空板,2表示颜色数)。所以:113是一列的配置数,非常适合7位。对于7列,我们需要7 * 7:= 49位。 (我们可能会为L / R镜像对称保存一位,甚至可能保留一个用于颜色对称,但这只会使事情变得复杂,恕我直言。)
仍然浪费了大量的编码空间(列不独立,板上As的数量等于B的数量,或者一个等等),但我不要认为避免它们很容易。幸运的是,没有必要。
答案 1 :(得分:2)
放大wildplasser:用于区分每个n位字符串与每个其他n位字符串的每个散列函数不能具有短于n位的输出。较短的哈希函数是可用的,因为我们只需要避免实际到达的字符串中的冲突,但我们不能希望离线进行智能选择。只需使用加密安全的RNG,就会发生以下两种情况之一:(i)您的代码将起作用,就好像RNG是真正随机的,或者(ii,不太可能)您的代码将会中断并且(如果它没有被窃听)它将充当密码RNG和真正的随机性之间的区别,给你带来名声和恶名。
答案 2 :(得分:1)
稍微通过wildplasser扩展答案,这里有一个关于如何实现propertyIsNotFullfilled
的想法。
将伪随机数集表示为{0,1} - 矩阵。执行Gaussian elimination(使用XOR而不是通常的乘法/减法运算)。如果得到最后一行为零的矩阵,则返回true
,否则返回false
。
当然,当集合的大小接近64时,此函数将非常频繁地返回true
。因此,OP中的算法仅对相对较小的大小有效。
要优化此算法,您可以保留最后一次高斯消除的结果。