Алгоритм для инкремента String неочевидным образом
Я хочу создать случайные 5 или 6 символьные буквенно-цифровые строки, например:
Vg78KY
Ответы на создание (псевдо) случайных строк были заданы, но мне интересно, существует ли алгоритм для приращения a String неочевидным образом. Простое приращение приведенной выше строки может дать:
Vg78KZ
Но я не хочу, чтобы следующая строка была угадана, я хочу, чтобы она выглядела совершенно иначе. Конечно, последовательные приращения не должны приводить к предыдущему результату, поскольку каждый из них должен быть уникальным.
Любые мысли о том, как добиться этого, очень ценятся!
Спасибо
Ответы
Ответ 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 будут полностью разными.