#javascript #arrays #loops #random #hash
Вопрос:
Представьте два разных массива:
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:
Я не уверен в том, как люди реализуют Math.random в javascript, но я знаю это в 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
Таким образом, вы можете использовать свой хэш-номер в качестве посева и сгенерировать серию псевдослучайных чисел. В принципе, вам нужно место для хранения вашего семени и его замены при вызове генератора случайных чисел (и не забудьте применить хэш-функцию).
Случайность полностью зависит от вашего выбора хэш-функции, и нелегко доказать, что вы получаете хорошую хэш-функцию для генерации случайных чисел (например, в большинстве случаев нам нужна хэш-функция равномерного распределения, и производительность тоже имеет значение). Но я верю, что есть литература, которая сделает эти доказательства для вас.
Комментарии:
1. Интересно, значит, вы используете результат первого хэширования на первой итерации, передаете его в ту же функцию (повторное хэширование результата первого хэширования) и т. Д. И т. Д., Пока не получите желаемый результат?
2. @Ress Это не до тех пор, пока у вас не будет желаемого результата, это ваш результат каждый раз. Поскольку трудно решить, когда вы получите желаемый результат, поэтому хорошая хэш-функция должна возвращать результаты с достаточной случайностью, это просто процесс выбора лучшей хэш-функции. en.cppreference.com/w/cpp/numeric/random На этой странице в разделе
Random number engines
вы сможете найти различные алгоритмы , реализованные на C/C . Я помню, что они используют очень большуюa
иc
в реализации C3.@Ress и нашел это en.wikipedia.org/wiki/Linear_congruential_generator для раздела
Parameters in common use
он описывает значенияa
c
m
, используемые во многих реализациях, надеюсь, это поможет.4. Сама хэш-функция у меня уже есть, просто я не подумал реализовать ее так, как вы упомянули. Всякий раз, когда я вернусь к этому, я попробую это решение. Спасибо!
5. Эй, Санху, я вернулся к этому, чтобы сказать, что твое решение сработало. Большое вам спасибо! Кроме того, у меня была проблема в исходном коде, когда
arr.length
он менялся из-за сращивания, что означало, что выполнение остановилось на полпути. Просто нужно было заранее сохранить исходную длину в переменной.
Ответ №2:
Почему вы делите ranNum
на «я»?
let rand = Math.floor(f * arr.length);
Должно быть все в порядке, потому что вы уменьшаетесь arr.length
с каждой итерацией. Кроме того, я не уверен в увеличении i
и удалении элемента из массива, что одновременно влияет на состояние цикла. Может быть, просто используйте while
петлю.
Комментарии:
1. Или установите переменную на исходную длину и используйте ее в условии итерации.
2. Проблема с этим решением заключается в том, что значение
f*arr.length
не будет сильно меняться при каждом уменьшенииarr.length
. Это будет точно так же, как и в предыдущей итерации, или на 1 меньше.