Подтвердить что ты не робот

Алгоритм для инкремента String неочевидным образом

Я хочу создать случайные 5 или 6 символьные буквенно-цифровые строки, например:

Vg78KY

Ответы на создание (псевдо) случайных строк были заданы, но мне интересно, существует ли алгоритм для приращения a String неочевидным образом. Простое приращение приведенной выше строки может дать:

Vg78KZ

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

Любые мысли о том, как добиться этого, очень ценятся!

Спасибо

4b9b3361

Ответ 1

Легкий подход, который позволяет избежать необходимости в поисковых таблицах:

  • Приращение целого числа обычно
  • Перенесение битов неочевидным способом (фиксированная перестановка, вероятно, прекрасна, но если вы хотите что-то более сложное, вы можете использовать что-то вроде George Marsaglia XORShift алгоритм, который создает псевдослучайную последовательность целых чисел, которая повторяется только после очень длительного цикла)
  • Преобразовать в закодированные строки Base64

Ответ 2

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

Я бы сделал что-то вроде этого:

  • Возьмите следующее целое число в последовательности.
  • Xor с фиксированным числом.
  • Переносить бит.
  • Кодировать номер с помощью Base64, Base36 и т.д.

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

Ответ 3

Что означает точно, если вы увеличиваете значение? Если вам просто нужны некоторые значения, которые являются результатом исходного значения, вы можете использовать хэш-код (возможно, криптографический хеш). Затем просто закодируйте его таким образом, чтобы использовать символы, которые вы хотите использовать (например, Base64 или что-то подобное) и вырезать его с количеством символов, которое вы хотите.

Это односторонняя операция. Это означает, что вы можете легко получить преемника значения, но не можете легко получить предшественника.

Ответ 4

import java.util.UUID;
public class RandomStringUUID {

    public static void main(String[] args) {

        UUID uuid = UUID.randomUUID();
        String randomUUIDString = uuid.toString();

        System.out.println("Random UUID String = " + randomUUIDString);
        System.out.println("UUID version       = " + uuid.version());
        System.out.println("UUID variant       = " + uuid.variant());

    }
}

Если вы хотите создать безопасные строки для столкновений, используйте UUID

Ответ 5

Если вы хотите, чтобы он был увеличен, это означает, что у вас есть функция преобразования F(), которая преобразуется из одного пространства в другое.

Итак, у вас, вероятно, есть функция из {Z} → {SomeString}

Итак, что вам нужно сделать, просто примените противоположное значение F() (F-1) к строке, получите исходное число, увеличьте его и сгенерируйте снова.

в псевдокоде:

int i = 1;
String s = Transform(i);
int num = UnTransform(s);
num++;
String next = Transform(num);

Ответ 6

Как насчет этого:

  • преобразовать число в двоичный формат;
  • изменить порядок цифр с помощью фиксированного ручного сопоставления (последняя цифра на 6-е место и т.д.);
  • преобразовать число обратно в хэш

Ответ 7

Еще один простой способ сделать это:

$hash_key = array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
$hash_table = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');

$init = 10000000;
$hash_value = str_replace($hash_key, $hash_table, strval($init));

//$hash_value = 'BAAAAAAA'

//For next value:
$init++;
$hash_value = str_replace($hash_key, $hash_table, strval($init));
//$hash_value = 'BAAAAAAB'

//If you want to increment only the string without knowing the digits:
$prev_hash = $hash_value;
$prev_init = intval(str_replace($hash_table, $hash_key, $prev_hash));
//$prev_init = 10000001

$next_init = $prev_init + 1;
$next_hash = str_replace($hash_key, $hash_table, strval($next_init));
//$next_hash = 'BAAAAAAC'

Надеюсь, это поможет.: -)

Ответ 8

Одним из возможных решений было бы предварительно сгенерировать весь словарь всех возможных строк, а затем использовать SecureRandom для указания индекса этого словаря. Если конкретный элемент уже будет "зарезервирован", вы просто перейдете к следующему доступному (эта операция также может быть предварительно сгенерирована btw).

Очевидным недостатком этого решения является недетерминизм. Но это не было запрошено OP. И я даже не уверен, что в этой ситуации возможен детерминизм.

Ответ 9

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

В конечном итоге это, вероятно, будет интенсивно работать как с памятью, так и с процессором.

Ответ 10

Вы можете попробовать и преобразовать следующий Python на язык по вашему выбору...

>>> import string, random, itertools
>>> digits = list(string.ascii_lowercase + string.ascii_uppercase + string.digits + '_')
>>> ''.join(digits)
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'
>>> digit_count = 4
>>> alldigits = [digits[:] for i in range(digit_count)]
>>> for d in alldigits: random.shuffle(d)

>>> numbergen = (''.join(d) for d in itertools.product(*alldigits))
>>> numbergen.__next__()
'B1xx'
>>> numbergen.__next__()
'B1x1'
>>> numbergen.__next__()
'B1xQ'
>>> numbergen.__next__()
'B1x7'

Ответ 11

Ну, так как вы хотите, чтобы строка была буквенно-цифровой, это довольно просто. Создайте массив символов размером 62. Это 26 строчных букв, 26 прописных букв и 10 цифр 0-9. После того, как вы заполните массив, пропустите N раз, где N - длина вашей строки, каждый раз выбирая случайный индекс. Поэтому он должен выглядеть примерно так:

   char [] arrayOfCharacters = new char[62];
   int index = 0;
   for(char a = 'a';a<= 'z';a++)
   {
           arrayOfCharacters[index++] = a;
   }//copy this loop for the upper case characters and 0-9
   String randomString = "";
   for(int x = 0;x < N; x++)
   {
           randomString += arrayOfCharacters[(int)(Math.random() * arrayOfCharacters.length)];
   }

Ответ 12

Что мой код.. он делает именно то, что вы просили использовать UUID для генерации строки, а затем выполнить (-) из нее.

import java.util.*;
class KeyGen {
    public static void main(String[] args) {
        String uuid = UUID.randomUUID().toString();
        String str = uuid.replaceAll("[-]", "").toUpperCase();
        String s = "";
        Scanner scan = new Scanner(System.in);
        String[] array = str.split("");
        Random rnd = new Random();
        int N = rnd.nextInt(str.length());
        System.out.println("How many keys you want?");
        int keys = scan.nextInt();
        String[] rndstr = new String[keys];
        System.out.println("How many letters for the first key?");
        int count = scan.nextInt();
        for (int t = 0; t < keys; t++)
        {
            s="";
            count++; 
            for(int i=0; i < count; i++)
                {
                    uuid = UUID.randomUUID().toString();
                    str = uuid.replaceAll("[-]", "").toUpperCase();
                    int len = str.length();
                    N= rnd.nextInt(len) + 1;
                    s = s + array[N]; 
                }
            rndstr[t] = s;
        }
        for (int j=0; j < rndstr.length; j++)
        {
            System.out.println(rndstr[j]);
        } 
}
} 

Простой вывод:

How many keys you want?
4
How many letters for the first key?
6

Here are your keys:
5F2934A
C8A456A6
B06E49240
FE3AE40CCE

Ответ 13

Сделайте вашу строку результатом операции хеширования. Например, используя ваши случайные строки в качестве входных данных:

String input1 = "Vg78KY";
String output1 = String.valueOf(input1.hashCode());

String input2 = "Vg78KZ";
String output2 = String.valueOf(input2.hashCode());

output1 и output2 будут полностью разными.