Я бы хотел случайным образом перебрать диапазон. Каждое значение будет посещено только один раз, и все значения будут в конечном итоге посещены. Например:
class Array
def shuffle
ret = dup
j = length
i = 0
while j > 1
r = i + rand(j)
ret[i], ret[r] = ret[r], ret[i]
i += 1
j -= 1
end
ret
end
end
(0..9).to_a.shuffle.each{|x| f(x)}
, где f(x)
- некоторая функция, которая работает с каждым значением. * * * * * * * * * * * * * * * * * * * * * * * * * * * * *1006*
Моя проблема в том, что shuffle
должен работать с массивом, что не здорово, потому что я работаю с астрономически большими числами. Ruby быстро потребляет большой объем оперативной памяти, пытаясь создать чудовищный массив. Представьте себе замену (0..9)
на (0..99**99)
. По этой же причине следующий код не будет работать:
tried = {} # store previous attempts
bigint = 99**99
bigint.times {
x = rand(bigint)
redo if tried[x]
tried[x] = true
f(x) # some function
}
Этот код очень наивен и быстро исчерпывает память, поскольку tried
получает больше записей.
Какой алгоритм может выполнить то, что я пытаюсь сделать?
[Edit1] : Почему я хочу это сделать? Я пытаюсь исчерпать пространство поиска алгоритма хеширования для входной строки N-длины в поисках частичных коллизий. Каждое число, которое я генерирую, эквивалентно уникальной входной строке, энтропии и всему. По сути, я "считаю", используя пользовательский алфавит .
[Edit2] : Это означает, что f(x)
в вышеприведенных примерах является методом, который генерирует хэш и сравнивает его с постоянным целевым хешем для частичных коллизий. Мне не нужно сохранять значение x
после вызова f(x)
, поэтому память должна оставаться постоянной с течением времени.
[Edit3 / 4/5/6] : дальнейшие разъяснения / исправления.
[Решение] : следующий код основан на решении @ bta. Для краткости next_prime
не отображается. Он производит приемлемую случайность и посещает каждое число только один раз. См. Фактическое сообщение для более подробной информации.
N = size_of_range
Q = ( 2 * N / (1 + Math.sqrt(5)) ).to_i.next_prime
START = rand(N)
x = START
nil until f( x = (x + Q) % N ) == START # assuming f(x) returns x