Алгоритм увеличения Строки неочевидным способом - PullRequest
16 голосов
/ 06 июля 2011

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

Vg78KY

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

Vg78KZ

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

Любые мысли о том, как этого добиться, приветствуются!

Спасибо

Ответы [ 13 ]

26 голосов
/ 06 июля 2011

Простой подход, который устраняет необходимость в таблицах поиска, будет следующим:

  • Обычно увеличивают целое число
  • Перестановка битов неочевидным способом (вероятно, фиксированная перестановкахорошо, но если вы хотите что-то более сложное, вы можете использовать что-то вроде алгоритм XORShift Джорджа Марсальи , который производит псевдослучайную последовательность целых чисел, которая повторяется только после очень длинного цикла)
  • Преобразовать в Base64 кодированные строки
3 голосов
/ 06 июля 2011

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

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

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

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

2 голосов
/ 06 июля 2011
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

2 голосов
/ 06 июля 2011

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

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

1 голос
/ 07 июля 2011

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

$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'

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

1 голос
/ 06 июля 2011

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

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

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

Таким образом, у вас, вероятно, есть функция из {Z}-> {SomeString}

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

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

int i = 1;
String s = Transform(i);
int num = UnTransform(s);
num++;
String next = Transform(num);
0 голосов
/ 25 октября 2013

Это мой код ... он делает именно то, что вы просили, используя 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
0 голосов
/ 07 июля 2011

Ну, так как вы хотите, чтобы строка была буквенно-цифровой, то это довольно просто. Создайте массив символов размером 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)];
   }
0 голосов
/ 07 июля 2011

Вы можете попробовать конвертировать следующий 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'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...