java - pilas - programa analizador de parentesis, llaves y corchetes "(){}[] " c++
Algoritmo para incrementar una cadena de una manera no obvia (13)
Quiero crear cadenas alfanuméricas de 5 o 6 caracteres de aspecto aleatorio, algo así como:
Vg78KY
Se ha respondido la creación de cadenas (pseudo) aleatorias, pero me pregunto si existe un algoritmo para incrementar una cadena de manera no obvia. Un simple incremento de la cadena anterior podría producir:
Vg78KZ
Pero no quiero que la próxima Cadena se pueda adivinar, quiero que se vea completamente diferente. Por supuesto, los incrementos sucesivos no deben producir un resultado previo, ya que cada uno debe ser único.
Cualquier pensamiento sobre cómo lograr esto muy apreciado!
Gracias
¿Qué pasa con este?
- convertir el número a formato binario;
- cambie el orden de los dígitos mediante la asignación manual fija (último dígito al sexto lugar, etc.);
- convertir el número de nuevo a hash
¿Qué quieres decir exactamente con incremento? Si solo desea algunos valores que son el resultado del valor original, puede usar un código hash (posiblemente un hash criptográfico). Luego simplemente codifíquelo de manera que use los caracteres que desea usar (por ejemplo, Base64 o algo similar) y córtelo en la cantidad de caracteres que desee.
Esta es una operación unidireccional, sin embargo. Eso significa que puede obtener fácilmente un sucesor de un valor, pero no puede obtener fácilmente el predecesor.
Bueno, ya que quieres que la cadena sea alfanumérica, entonces es bastante sencillo. Cree una matriz de caracteres del tamaño 62. Esto es 26 letras minúsculas, 26 letras mayúsculas y los 10 dígitos 0-9. Después de completar la matriz, recorra N veces, donde N es la longitud de su cadena, seleccionando un índice aleatorio cada vez. Entonces debería verse algo como esto:
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)];
}
Ese es mi código ... hace exactamente lo que pediste al usar el UUID para generar una cadena y luego ejecutar (-) desde él.
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]);
}
}
}
Salida simple:
How many keys you want?
4
How many letters for the first key?
6
Here are your keys:
5F2934A
C8A456A6
B06E49240
FE3AE40CCE
Haga su cadena el resultado de una operación de hash. Por ejemplo, usando sus cadenas aleatorias como entrada:
String input1 = "Vg78KY";
String output1 = String.valueOf(input1.hashCode());
String input2 = "Vg78KZ";
String output2 = String.valueOf(input2.hashCode());
output1 y output2 serán completamente diferentes.
Método perezoso: mantenga una tabla hash o un conjunto para almacenar todas las cadenas existentes, y cada vez que genere una cadena aleatoria, verifique si está en el conjunto. Si es así, genere uno nuevo hasta que obtenga uno que no esté en el conjunto.
Sin embargo, a largo plazo, probablemente esto requeriría mucho uso de memoria y procesador.
Otra forma simple de hacer esto sería:
$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''
Espero que esto ayude. :-)
Puedes probar y convertir el siguiente Python al idioma de tu elección ...
>>> 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''
Si asumimos que debe haber un mapeo 1: 1 de "número de secuencia" a "cadena de apariencia aleatoria", entonces el enfoque truncado de hash no funcionará ya que no hay garantía de que el hash truncado no esté sujeto a colisiones.
Haría algo como esto:
- Tome el siguiente entero en secuencia.
- Xor con un número fijo.
- Permuta los bits.
- Codifica el número usando Base64, Base36, o lo que sea.
Tenga en cuenta que esto estará sujeto a un fácil análisis por parte de un atacante determinado con acceso a un conjunto suficientemente grande de números de secuencia.
Si desea que se incremente, significa que tiene alguna función de transformación F () que se transforma de un espacio a otro.
Así que probablemente tenga una función de {Z} -> {SomeString}
Entonces, lo que debe hacer es aplicar el opuesto de F () (F-1) a la cadena, obtener el número original, incrementarlo y volver a generarlo.
en pseudocódigo
int i = 1;
String s = Transform(i);
int num = UnTransform(s);
num++;
String next = Transform(num);
Un enfoque fácil que evite la necesidad de tablas de búsqueda sería:
- Incrementar un entero normalmente
- Permuta los bits de una manera no obvia (una permutación fija probablemente esté bien, pero si desea algo más sofisticado, podría usar algo como el algoritmo XORShift de George Marsaglia que produce una secuencia psíquica de números enteros que solo se repite después de un ciclo muy largo)
- Convertir a cadenas codificadas en Base64
Una de las posibles soluciones sería generar previamente el diccionario completo de todas las cadenas posibles y luego usar SecureRandom
para apuntar a un índice de ese diccionario. Si un elemento en particular ya estuviera "reservado", simplemente iría al siguiente disponible (esta operación también puede generarse previamente por cierto).
La desventaja obvia de esta solución es el no determinismo. Pero esto no fue solicitado por OP. Y ni siquiera estoy seguro de si el determinismo es posible en esta situación.
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());
}
}
Si desea generar cadenas de seguridad contra colisiones solo use los UUID