Как детерминистически объединить целые так, чтобы они всегда генерировали уникальные значения?

1

У меня есть set случайно сгенерированных ints и функция evolve(set) которая принимает набор, удаляет два ints и вставляет 4 новых ints. Я хочу, чтобы набор никогда не повторял ints. То есть независимо от того, сколько раз я применяю evolve(evolve(...evolve(set))), она никогда не должна иметь дублированных значений.

Что такое простой способ combine(int x, int y) → int который гарантирует это свойство с высокой вероятностью?

Пример:

// Helpers.
var range = length => Array.from({length}, i => i);
var random = () => (Math.random() * Math.pow(2,31) | 0);
var removeRandom = set => set.splice(random() % set.length, 1)[0];
var hasRepeated = set => !set.sort((a,b) => a - b).reduce((a,b) => a && a !== b && b || 0, -1);

// Receives two parent ints, returns 4 derived ints.
// Can't use random() here; it must generate 4 ints
// from simple functions (multiplication, bitwise
// operations, etc.) of 'a' and 'b'.
function combine(a, b) {
  return [a + b + 0, a + b + 1, a + b + 2, a + b + 3];
};

// Removes two ints from set, inserts 4 ints.
function evolve(set) {
  var a = removeRandom(set);
  var b = removeRandom(set);
  set.push(...combine(a,b));
};

// Random initial set of ints.
var set = range(64).map(random);

// No matter how many times 'evolve' is applied, 
// the set should never have repeated ints.
for (var i = 0; i < 50000; ++i) {
  evolve(set);
}

// Prints 'true' if algorithm is correct
// (no repeated number was generated).
console.log(!hasRepeated(set));

Обратите внимание, что здесь combine(a,b) просто добавляет их вместе. Это плохой выбор; с целым 50000 звонками для evolve, он уже не прошел тест. Я мог бы использовать линейный конгруэнтный генератор, но мне интересно, может ли он быть проще, чем при этих условиях. Возможно, использование XOR?

  • 2
    const range = length => Array.from({length}, i => i); и const hasRepeated = set => (new Set(set)).size !== set.length
  • 1
    @JonasW. woops, я только что спросил об этом на #javascript, но забыл его использовать. Под редакцией!
Показать ещё 27 комментариев
Теги:
algorithm
random

1 ответ

0

Если у вас есть пространство для хранения массива с юниверсом возможных записей, вы можете просто рандомизировать его, а затем отслеживать индексы, которые связывают ваш набор, увеличивая начальный индекс, чтобы удалить элементы и конечный индекс, чтобы добавить их.

Вы можете либо рандомизировать весь массив вперед, либо по мере увеличения индекса окончания.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню