Представьте, что я смог перетасовать все числа от 0 до 2 ^ 32, используя что-то вроде перемешивания Кнута и генератора случайных чисел, засеянного ключом.
Концептуально, мне понадобятся два массива (используя Z 5 вместо Z 2 32 для краткости):
[2, 0, 1, 4, 3] // perm
[1, 2, 0, 4, 3] // inv === p^-1
ЕслиУ меня были эти массивы, я мог бы эффективно найти n-й элемент в перестановке, а также узнать с помощью элемента в значении пурмутации v;
v = perm[n];
n == inv[v]; // true
Я не хочу хранить два массива по 16 ГБuint, представляющий это перемешанное множество, потому что я никогда не интересуюсь всей перемешанной последовательностью.Меня интересует только значение n-го элемента.
В идеале я хочу написать две чистые функции, которые работают так:
uint nthShuffled = permutate<uint>(key, n); // O(log n)
uint n == invert<uint>(key, nthShuffled); // O(log n)
Требования:
- Каждое 32-битное значение соответствует уникальному другому 32-битному значению.
- Знание первых 100 элементов в перестановке не дает информации о том, что может быть 101-м элементом в перестановке.
Я понимаю, что в теории должно быть не менее 2 32 !уникальные ключи для представления любой возможной перестановки, но я полагаю, что на практике я могу скрыть эту проблему за хорошей функцией хеширования.
Есть ли что-нибудь, что близко к этому?