Generate a random Alphanumeric String without some characters - java

I want to generate a random Alphanumeric String. I want to exlude some characters from my string
l, i, o and the number 0
For the moment i have this code:
import org.apache.commons.lang.RandomStringUtils;
...
numberFile = RandomStringUtils.randomAlphanumeric( 5 );

Since you are using RandomStringUtils you might aswell use the designated RandomStringUtils#random method for that.
public static String random(int count,
int start,
int end,
boolean letters,
boolean numbers,
char... chars)
Parameters:
count - the length of random string to create
start - the position in set of chars to start at
end - the position in set of chars to end before
letters - only allow letters?
numbers - only allow numbers?
chars - the set of chars to choose randoms from. If null, then it will use the set of all chars.
See the docs here.

Construct an array with the element from which your string want to be built upon.
Let's say C={a,b,c,d....,1,2,3..} has size n
Generate n random numbers in the range [0,n-1], for example D={3,5,1,0,2..}.
Now if you build a string s from D as follows:s[i] = C[D[i]] what you get is a random string from a set of chars defined in C, which a guess is exactly what you want.
You can easily make C such that it does not contain the set of characters you don't want to appear in your random String.

Turning Davide Spataro's answer into code without using any 3rd party library could look like this:
private static final String ALPHABET = "123456789abcdefghjkmnpqrstuvwxyz";
public static String generateRandomString(int length) {
Random random = ThreadLocalRandom.current();
int alphabetLength = ALPHABET.length();
char[] chars = new char[length];
for (int i = 0; i < length; i++)
chars[i] = ALPHABET.charAt(random.nextInt(alphabetLength));
return String.valueOf(chars);
}
Or alternatively a Java 8 Stream based approach:
public static String generateRandomStringJava8(int length) {
return IntStream.range(0, length)
.map(i -> ThreadLocalRandom.current().nextInt(ALPHABET.length()))
.mapToObj(i -> ALPHABET.substring(i, i + 1))
.collect(Collectors.joining());
}
Both methods generate Strings of given length by picking length random characters from the static ALPHABET.

Related

Extremely compact UUID (using all alphanumeric characters)

I need an extremely compact UUID, the shorter the better.
To that end, I wrote:
public String getBase36UIID() {
// More compact version of UUID
String strUUID = UUID.randomUUID().toString().replace("-", "");
return new BigInteger(strUUID, 16).toString(36);
}
By executing this code, I get, for example:
5luppaye6086d5wp4fqyz57xb
That's good, but it's not the best. Base 36 uses all numeric digits and lowercase letters, but does not use uppercase letters.
If it were possible to use uppercase letters as separate digits from lowercase letters, it would be possible to theorize a numerical base 62, composed of these digits:
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
I could theorize numerical bases also using accented characters such as "รจ" or "รฉ", or special characters such as "$" or "!", further increasing the number of digits available.
The use of these accented or special characters, however, may cause me problems, so for the moment I prefer not to consider them.
After all these premises, how can I convert the BigInteger representing my UUID into the base 62 above theorized, in order to make it even more compact? Thanks
I have already verified that a code like the following is not usable, because every base over 36 is treated as base 10:
return new BigInteger(strUUID, 16).toString(62);
After all, in mathematics there is no base 62 as I imagined it, but I suppose that in Java it can be created.
The general algorithm for converting a number to any base is based on division with remainder.
You start by dividing the number by the base. The remainder gives you the last digit of the number - you map it to a symbol. If the quotient is nonzero, you divide it by the base. The remainder gives you the second to last digit. And you repeat the process with the quotient.
In Java, with BigInteger:
String toBase62(BigInteger number) {
String symbols = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
BigInteger base = BigInteger.valueOf(symbols.length());
StringBuilder result = new StringBuilder();
do {
BigInteger[] quotientAndRemainder = number.divideAndRemainder(base);
number = quotientAndRemainder[0];
result.append(symbols.charAt(quotientAndRemainder[1].intValue()));
} while (number.compareTo(BigInteger.ZERO) > 0);
return result.reverse().toString();
}
Do you need the identifier to be a UUID though? Couldn't it be just any random sequence of letters and numbers? If that's acceptable, you don't have to deal with number base conversions.
String randomString(int length) {
String symbols = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
Random rnd = new Random();
StringBuilder str = new StringBuilder();
for (int i = 0; i < length; i++) {
str.append(symbols.charAt(rnd.nextInt(symbols.length())));
}
return str.toString();
}
This should not be difficult. Converting a number to a string is a basic programming task. The fact that you're using base 62 makes no difference.
Decide how many characters you're willing to use, and then convert your large number to that base. Map each "digit" onto one of the characters.
Pseudocode:
b = the base (say, 62)
valid_chars = an array of 'b' characters
u = the uuid
while u != 0:
digit = u % b;
char = valid_chars[digit];
u = u / b;
This produces the digits right-to-left but you should get the idea.
Main idea is the same as previous posts, but the implementation have some differences.
Also note that if wanted different occurrence probability for each chars this can be adjusted also.(mainly add a character more time on a data structure and change his probability)
Here is fair-probability for each chars (equals, 1/62)
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class RCode {
String symbols = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static void main(String[] args)
{
RCode r = new RCode();
System.out.println("symbols="+r.symbols.length());
System.out.println("code_10(+1)="+r.generate(10));
System.out.println("code_70(+2)="+r.generate(70));
//System.out.println("code_124(+3)="+r.generate(124));
}
public String generate(int length)
{
int num = length/symbols.length()+1;
List<Character> list = new ArrayList<Character>();
for(int i=0; i<symbols.length(); i++)
{
//if needed to change probability of char occurrence then adapt here
for(int j=0;j<=num;j++)
{
list.add(symbols.charAt(i));
}
}
//basically is the same as random
Collections.shuffle(list);
StringBuffer sb = new StringBuffer();
for(int i=0; i<length; i++)
{
sb.append(list.get(i));
}
return sb.toString();
}
}
Output:
symbols=62
//each char is added once(+1)
code_10(+1)=hFW9ZFEAeU
code_70(+2)=hrHQCEdQ3F28apcJPnfjAaOu55Xso12xabkJ7MrU97U0HYkYhWwGEqVAiLOp3X3QSuq6qp
Note: Algorithm have a defect, just try to figured out why the sequence will be never generate on 10 (aaaaaaaaaa). Easy to fix ... but i was focused on the idea.
Now, as it is, basically is generating up to num each character. (random and maybe for someone will be useful the output)

Removing a single char from a string of letters based on a number position in JAVA [duplicate]

This question already has answers here:
How to remove single character from a String by index
(23 answers)
Closed 4 years ago.
To give some context to the title, let's say I have an array of INTs. So, for example (1,2,3,4,5).
Each number in the array represents a char in a string. So if the string is hello then array[3] is going to represent "l".
What is the most efficient or simplest way to remove a char from a string, replace the char and then add it back into the string?
So using the example above I could change "l" to "d", add it back to the string so my final string is "hedlo".
here is part of my code:
method used for max:
public static int getMax(int[] inputArray){
int maxValue = inputArray[0];
for(int i=1;i < inputArray.length;i++){
if(inputArray[i] > maxValue){
maxValue = inputArray[i];
}
}
return maxValue;
}
here is the code for using the max value in the array as the position in the string results to edit. The char to edit should be replaced with an "m" in the actual case
int max = getMax(array);
results.setCharAt(max, 'm');
String result = results.toString();
Yes, it can easiyl be done. Below I have some code from https://stackoverflow.com/a/4576556/9354346
StringBuilder str = new StringBuilder("hello");
str.setCharAt(2, 'd');
String result = str.toString();
Without knowing why you're doing this, I'm not sure exactly what to recommend but here's something to think about. ASCII characters have numerical values associated with them. Table.
If you cast an int to a char, it will convert it to that value. So like,
char c = (char) 97;
would evaluate to 'a.' If you want 'a' to start at 1, you could just add 96 to everything.
To convert, you could add to an int the difference in the table. So from 'a' to 'd', add 3.
EDIT:
I answered this assuming you were changing an array of ints that was representing a string. Re-reading the question, I'm not sure that's what you're doing! If you need to change a character of a string to a different character, you can use the substring function to grab characters before the change, and after the change and put the new character in the middle.
String x = "Hello";
x = x.substring(0,2) + 'd' + x.substring(3);
This makes x say "Hedlo."

Java: How do I loop through characters in a string that have a surrogate pair and print them?

I tried this to loop through the characters in my string and print them. All of them are printing fine except the Deseret Long I (๐€). I have no idea if there are other ways to do this so that the ๐€ is printed correctly. Here is my code:
package javaapplication13;
public class JavaApplication13 {
public static void main(String[] args) {
String s = "h๐คกy๐€\u0500";
System.out.println(s);
final int length = s.length();
for (int offset = 0; offset < length;) {
final int codepoint = s.codePointAt(offset);
System.out.println((char) (codepoint));
offset += Character.charCount(codepoint);
}
}
}
The output looks like this (Netbeans):
run:
h๐คกy๐€ิ€
h
ไก
y
ะ€
ิ€
BUILD SUCCESSFUL (total time: 0 seconds)
Your problem is caused by the fact that you try to convert int to char (4 bytes to 2 bytes). The value in the codepoint variable cannot fit in one char in case of surrogate pair. Look, it is called pair, because it is a pair of chars. I think the simplest way how you can print it is by using String.Substring() method. Or you can convert it to array of char's this way: char[] ch = Character.toChars(codepoint); and you can convert this array back to string by simple new String(ch).

Why will this java string routine not print the answer?

I have been working on the Project Euler problem 4. I am new to java, and believe I have found the answer (906609 = 993 * 913, by using Excel!).
When I print the line commented out, I can that my string manipulations have worked. I've researched a few ways to compare strings in case I had not understoof something, but this routine doesn't give me a result.
Please help me identify why it is not printing the answer?
James
public class pall{
public static void main(String[] args){
int i;
int j;
long k;
String stringProd;
for(i=994;i>992; i--){
for (j=914;j>912; j--){
k=(i*j);
stringProd=String.valueOf(k);
int len=stringProd.length();
char[] forwards=new char[len];
char[] back = new char[len];
for(int l=0; l<len; l++){
forwards[l]=stringProd.charAt(l);
}
for(int m=0; m<len;m++){
back[m]=forwards[len-1-m];
}
//System.out.println(forwards);
//System.out.println(back);
if(forwards.toString().equals(back.toString())){
System.out.println(k);}
}
}
}
}
You are comparing the string representation of your array. toString() doesn't give you what you think. For example, the below code makes it clear:
char[] arr1 = {'a', 'b'};
char[] arr2 = {'a', 'b'};
System.out.println(arr1.toString() + " : " + arr2.toString());
this code prints:
[C#16f0472 : [C#18d107f
So, the string representation of both the arrays are different, even though the contents are equal. This is because arrays don't override toString() method. It inherits the Object#toString() method.
The toString method for class Object returns a string consisting of
the name of the class of which the object is an instance, the at-sign
character #, and the unsigned hexadecimal representation of the hash
code of the object. In other words, this method returns a string equal
to the value of:
getClass().getName() + '#' + Integer.toHexString(hashCode())
So, in the above output, [C is the output of char[].class.getName(), and 18d107f is the hashcode.
You can't also compare the arrays using forward.equals(back), as arrays in Java don't override equals() or hashCode() either. Any options? Yes, for comparing arrays you can use Arrays#equals(char[], char[]) method:
if (Arrays.equals(forward, back)) {
System.out.println(k);
}
Also, to get your char arrays, you don't need those loops. You can use String#toCharArray() method. And also to get the reverse of the String, you can wrap the string in a StringBuilder instance, and use it's reverse() method:
char[] forwards = stringProd.toCharArray();
char[] back = new StringBuilder(stringPod).reverse().toString().toCharArray();
And now that you have found out an easy way to reverse a string, then how about using String#equals() method directly, and resist creating those character arrays?
String stringPod = String.valueOf(k);
String reverseStringPod = new StringBuilder(stringPod).reverse().toString()
if (stringPod.equals(reverseStringPod)) {
System.out.println(k);
}
Finally, since it is about project euler, which is about speed and mostly mathematics. You should consider avoiding String utilities, and do it with general division and modulus arithmetic, to get each individual digits, from beginning and end, and compare them.
To convert a string to char[] use
char[] forward = stringProd.toCharArray();
To convert a char[] to String, use String(char[]) constructor:
String backStr = new String(back); // Not the same as back.toString()
However, this is not the most performant solution, for several reasons:
You do not need to construct a back array to check if a string is a palindrome - you can walk the string from both ends, comparing the characters as you go, until you either find a difference or your indexes meet in the middle.
Rather than constructing a new array in a loop, you could reuse the same array - in case you do want to continue with an array, you could allocate it once for the maximum length of the product k, and use it in all iterations of your loop.
You do not need to convert a number to string in order to check if it is a palindrome - you can get its digits by repeatedly taking the remainder of division by ten, and then dividing by ten to go to the next digit.
Here is an illustration of the last point:
boolean isPalindrome(int n) {
int[] digits = new int[10];
if (n < 0) n = -n;
int len = 0;
while (n != 0) {
digits[len++] = n % 10;
n /= 10;
}
// Start two indexes from the opposite sides
int left = 0, right = len-1;
// Loop until they meet in the middle
while (left < right) {
if (digits[left++] != digits[right--]) {
return false;
}
}
return true;
}

Algorithm for incrementing a String in a non-obvious manner

I want to create random-looking 5 or 6 character alpha-numeric strings, something like:
Vg78KY
Creating (pseudo-)random Strings has been answered, but I am wondering if there is an algorithm for incrementing a String in a non-obvious manner. A simple increment of the above String might yield:
Vg78KZ
But I don't want this next String to be guessable, I want it to look completely different. Of course, successive increments should not yield a previous result as each should be unique.
Any thoughts on how to achieve this much appreciated!
Thanks
An easy approach that avoids the need for lookup tables would be:
Increment an integer normally
Permute the bits in a non-obvious way (a fixed permutation is probably fine, but if you want something more sophisticated you could use something like George Marsaglia's XORShift algorithm that produces a psuedorandom sequence of integers that only repeats after a very long cycle)
Convert to Base64 encoded strings
If we assume there must be a 1:1 mapping from "sequence number" to "random-looking string", then the truncated hash approach will not work as there is no guarantee that the truncated hash won't be subject to collisions.
I'd do something like this:
Take the next integer in sequence.
Xor with a fixed number.
Permute the bits.
Encode the number using Base64, Base36, or whatever.
Note that this will be subject to easy analysis by a determined attacker with access to a sufficiently large set of sequence numbers.
What exactly do you mean by increment? If you just want some values that is the result of the original value, the you can use a hash code (possibly a cryptographic hash). Then simply encode it a way that uses the characters you want to use (for example Base64 or something similar) and cut it off at the number of characters you want.
This is a one-way operation, however. That means that you can easily get successor of a value, but can't easily get the predecessor.
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());
}
}
If you want to generate collision safe strings just use UUIDs
If you want it to be incremented it means you have some transformation function F() that transforms from one space to another.
So you probably have a function from {Z} -> {SomeString}
So what you need to do, is just apply the opposite of F() (F-1) to the string, get the original number, increment it, and generate it again.
in pseudocode:
int i = 1;
String s = Transform(i);
int num = UnTransform(s);
num++;
String next = Transform(num);
What about this one:
convert the number to binary format;
change the order of digits by fixed manual mapping (last digit to 6th place, etc);
convert the number back to hash
Another simple way to do this would be:
$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'
Hope this helps. :-)
One of possible solutions would be to pre-generate the entire dictionary of all possible strings and then use SecureRandom to point to an index of that dictionary. If a particular element would already be "reserved", you'd simply go to the next available one (this operation can also be pre-generated btw).
The obvious disadvantage of this solution is non-determinism. But this was not requested by OP. And I'm not even sure if determinism is possible in this situation.
Lazy method: keep a hashtable or set to store all existing strings, and each time you generate a random string, check to see if it's in the set. If so, generate a new one until you get one that's not in the set.
This would probably be both memory- and processor-intensive in the long run, though.
You might try and convert the following Python to the language of your choice...
>>> 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'
Well since you want the string to be alphanumeric, then it's pretty straightforward. Create a character array of size 62. This is 26 lowercase letters, 26 uppercase letters, and the 10 digits 0-9. After you fill in the array, loop through N times, where N is the length of your string, selecting a random index each time. So it should look something like this:
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)];
}
That's my code.. it does exactly what you asked for using the UUID to generate a string then execute (-) from it.
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]);
}
}
}
Simple output:
How many keys you want?
4
How many letters for the first key?
6
Here are your keys:
5F2934A
C8A456A6
B06E49240
FE3AE40CCE
Make your string the result of a hash operation. For example, using your random strings as input:
String input1 = "Vg78KY";
String output1 = String.valueOf(input1.hashCode());
String input2 = "Vg78KZ";
String output2 = String.valueOf(input2.hashCode());
output1 and output2 will be completely different.

Categories