如何使用散列将元素从一个数组伪随机移动到另一个数组?
Posted
技术标签:
【中文标题】如何使用散列将元素从一个数组伪随机移动到另一个数组?【英文标题】:How can I move elements from one array to another pseudo-randomly using a hash? 【发布时间】:2021-10-20 17:35:00 【问题描述】:画出两个不同的数组:
let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let newArr = [];
我想要实现的是通过伪随机循环将元素从arr
移动到newArr
,这试图模仿Math.random()
的功能,除了唯一的随机性应该与固定的相反,哈希数。
我正在尝试这样的事情,但到目前为止没有运气:
const madeUpHash = "827354819373"
const floatIndex = "0."
const f = parseFloat(floatIndex + madeUpHash);
let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let newArr = [];
for (let i = 0; i < arr.length; i++)
let ranNum = (f/i); // this points towards 0, meaning the next Math.Floor will eventually always retrieve index 0
let rand = Math.floor(ranNum * arr.length);
newArr.push(...arr.splice(rand, 1))
这不仅不起作用,而且非常可怕。
有没有可靠的方法来实现这一目标?
我的另一个想法是遍历散列的各个数字(在将它们转换为数组之后)并创建一个随机数,例如ranNum = i/madeUpHash[i]
,但它会在i >= madeUpHash[i]
时立即中断,因为它会返回一个更大的正整数不止一个。
有什么想法吗?谢谢。
【问题讨论】:
【参考方案1】:我不确定人们是如何在 javascript 中实现 Math.random,但我知道 C 语言。
基本上,这个想法是,你有一个哈希函数hash
,和一个种子s
,你申请hash(s)
来得到你的X_0
,对于X_(n+1)
,你做X_(n+1) = hash(X_n)
。
只要你为你的随机性选择一个具有一定分布的好的散列函数,如果种子相同,就非常容易和一致。
对于C,他们正在做Linear Congruential Generator
X_(n+1) = (a * X_n + b) % m
因此,您可以将哈希数用作种子并生成一系列伪随机数。基本上,您需要一个地方来存储您的种子并在调用随机生成器时替换它(并且不要忘记应用哈希函数)。
随机性完全来自您对哈希函数的选择,要证明您获得了一个好的哈希函数来生成随机数并不容易(就像我们在大多数情况下想要一个均匀分布的哈希函数一样,性能也很重要)。但我相信有文献可以为你做这些证明。
【讨论】:
有趣,所以你在第一次迭代中使用第一次散列的结果,将它传递给同一个函数(重新散列第一次散列的结果)等等,直到你得到你想要的输出? @Ress 直到你有你想要的输出,它每次都是你的输出。因为很难决定什么时候会得到你想要的输出,所以一个好的散列函数应该返回具有足够随机性的结果,这纯粹是一个选择最佳散列函数的过程。 en.cppreference.com/w/cpp/numeric/randomRandom number engines
部分的此页面,您将能够找到 C/C++ 实现的不同算法。我记得他们在 C 实现中使用了非常大的 a
和 c
@Ress 发现 en.wikipedia.org/wiki/Linear_congruential_generator 部分 Parameters in common use
它描述了许多实现中使用的 a
c
m
的值,希望对您有所帮助。
哈希函数本身我已经有了,只是没有考虑按照你说的方式实现。每当我重新开始时,我都会尝试这个解决方案。谢谢!
嘿三虎,我回来说你的解决方案有效。太感谢了!此外,我在原始代码中遇到了一个问题,arr.length
由于拼接而发生变化,这意味着执行中途停止。只需事先将原始长度保存在变量中即可。【参考方案2】:
为什么要把ranNum
除以i?
let rand = Math.floor(f * arr.length);
应该没问题,因为您在每次迭代中都会减少arr.length
。此外,我不确定增加i
并从数组中删除一个元素,这会同时影响循环条件。也许只使用while
循环。
【讨论】:
或者设置一个变量为原来的长度,在迭代条件中使用。 这个解决方案的问题是f*arr.length
的值不会在每次减少arr.length
时发生很大变化。它将与上一次迭代相同或减少 1 次。以上是关于如何使用散列将元素从一个数组伪随机移动到另一个数组?的主要内容,如果未能解决你的问题,请参考以下文章