I have written this java method but sometimes the color String is only 5 characters long. Does anyone know why?
#Test
public void getRandomColorTest() {
for (int i = 0; i < 20; i++) {
final String s = getRandomColor();
System.out.println("-> " + s);
}
}
public String getRandomColor() {
final Random random = new Random();
final String[] letters = "0123456789ABCDEF".split("");
String color = "#";
for (int i = 0; i < 6; i++) {
color += letters[Math.round(random.nextFloat() * 15)];
}
return color;
}
Working with floats and using round is not a safe way of creating such random colors.
Actually a color code is an integer in hexadecimal formatting. You can easily create such numbers like this:
import java.util.Random;
public class R {
public static void main(String[] args) {
// create random object - reuse this as often as possible
Random random = new Random();
// create a big random number - maximum is ffffff (hex) = 16777215 (dez)
int nextInt = random.nextInt(0xffffff + 1);
// format it as hexadecimal string (with hashtag and leading zeros)
String colorCode = String.format("#%06x", nextInt);
// print it
System.out.println(colorCode);
}
}
DEMO
Your split will generate an array of length 17 with an empty string at the beginning. Your generator occasionally draws that zeroth element which will not contribute to the length of the final string. (As a side effect, F will never be drawn.)
Accept that split has that odd behaviour and work with it: Ditch that nasty formula that uses round. Use 1 + random.nextInt(16) instead as your index.
Don't recreate the generator on each call of getRandomColor: that ruins the generator's statistical properties. Pass random as a parameter to getRandomColor.
Also to ensure that your String always contains 6 characters, try to replace the for loop with a while. Please see:
while (color.length() <= 6){
color += letters[random.nextInt(17)];
}
Related
Hi I am trying to generate a 5 digit random number which is alpha numeric in nature. I am doing both with without using Streams.
CODE
public class AlphaRandom {
private static final String ALPHA_NUMERIC_STRING = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
static final Random random = new Random();
public static void main(String args[]) {
int length = 5;
String seq = randomAlphaNumeric(length);
System.out.println("Random Number Normal : " +seq);
IntStream.range(0,1).forEach(i->System.out.println("Random Number Streams : " +generateRandomString(random, length)));
}
// Using Streams
private static String generateRandomString(Random random, int length){
return random.ints(48,122)
.filter(i-> (i<57 || i>65) && (i <90 || i>97))
.mapToObj(i -> (char) i)
.limit(length)
.collect(StringBuilder::new, StringBuilder::append, StringBuilder::append)
.toString();
}
// Normal
public static String randomAlphaNumeric(int count) {
StringBuilder builder = new StringBuilder();
while (count-- != 0) {
int character = (int)(Math.random()*ALPHA_NUMERIC_STRING.length());
builder.append(ALPHA_NUMERIC_STRING.charAt(character));
}
return builder.toString();
}
}
Sample Outputs :
Random Number Normal : VYAXC
Random Number Streams : LdBN6
Random Number Normal : 2ANTT
Random Number Streams : hfegc
Random Number Normal : JWK4Y
Random Number Streams : 8mQXK
But I am unable to generate the sequence always starting with a UpperCase only.
Can someone help me out.
I will use RandomStringUtils from the apache library to do this. The reason to do this is less code and I believe better readability of the code.
This is my code which can do the required thing
import org.apache.commons.lang3.RandomStringUtils;
public class GenerateRandomString {
public static void main(String[] args) {
int keyLength = 5; // Number of character allowed as per requirement
String randomAlphanumeric = RandomStringUtils.randomAlphanumeric(keyLength);
System.out.println("randomAlphanumeric generated is " + randomAlphanumeric);
String upperCaseRandom = randomAlphanumeric.substring(0, 1).toUpperCase() + randomAlphanumeric.substring(1);
System.out.println("upperCaseRandom generated is " + upperCaseRandom);
}
}
It would generate the following output:
randomAlphanumeric generated is m8OiR
upperCaseRandom generated is M8OiR
I am making the first character to uppercase as required by question using the substring method.
The easiest way is that before to return your string (once you have generated it), you take the first letter in order to apply toUpperCase and on the remaining chars, apply toLowerCase. Also, if in the future you will need to generate longer strings, you can use the same method without changing anything.
Summering what we'll do is:
public static String manipulate (String rand){
String c = rand.substring(0,1); // where rand is the random alphanumeric generated by your methods, we pick the first char
c = c.toUpperCase(); //we make it upperCase
String split = rand.substring(1); //we get the remaining of the string starting from position 1
split = split.toLowerCase(); //let's apply lowercase on the remaining
String result = c+split; //join again
return result;
}
Full Code:
package test;
import java.util.Random;
import java.util.stream.IntStream;
public class AlphaRandom {
private static final String ALPHA_NUMERIC_STRING = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
static final Random random = new Random();
public static void main(String args[]) {
int length = 5;
String seq = randomAlphaNumeric(length);
System.out.println("Random Number Normal : " +seq);
IntStream.range(0,1).forEach(i->System.out.println("Random Number Streams : " +generateRandomString(random, length)));
}
public static String manipulate (String rand){
String c = rand.substring(0,1); // where rand is the random alphanumeric generated by your methods, we pick the first char
c = c.toUpperCase(); //we make it upperCase
String split = rand.substring(1); //we get the remaining of the string starting from position 1
split = split.toLowerCase(); //let's apply lowercase on the remaining
String result = c+split; //join the again
return result;
}
// Using Streams
private static String generateRandomString(Random random, int length){
String rand = random.ints(48,122)
.filter(i-> (i<57 || i>65) && (i <90 || i>97))
.mapToObj(i -> (char) i)
.limit(length)
.collect(StringBuilder::new, StringBuilder::append, StringBuilder::append)
.toString();
return manipulate(rand);
}
// Normal
public static String randomAlphaNumeric(int count) {
StringBuilder builder = new StringBuilder();
while (count-- != 0) {
int character = (int)(Math.random()*ALPHA_NUMERIC_STRING.length());
builder.append(ALPHA_NUMERIC_STRING.charAt(character));
}
return manipulate(builder.toString());
}
}
Output:
Random Number Normal : Mwwsz
Random Number Streams : Q1fqk
New to arrays here... I want to get a random integer and set that integer to each individual letter in the alphabet like integer 1 = a. So that I can print a random letter in the alphabet without using a pre-existing java method for random string. I don't want to generate a random string this is the way I need it.
{
public static void main(String[] args)
{
Random Gen = new Random();
String[] letters = new String[50];
String alphabet = "abcdefghijklmnopqrstuvwxyz";
int randomInt = Gene.nextInt(26);
String second = "" + randomInt;
System.out.println(second);
//Not sure what next....
}
}
System.out.println(alphabet.charAt(randomInt)) will print the character at (zero-based) position randomInt in your alphabet string.
(Note that randomInt == 0 will output a, 1 outputs b and so on.)
Adapt this to your need.
There is an alternative way of selecting a random character, this is in my opinion a more elegant solution if all you will ever need is lowercase characters. It more explicitly conveys that the generated character will be a random lowercase latin letter, because it does not use an alphabet string constant.
public static void main(final String args[]) {
final Random random = new Random();
final String[] array = new String[50];
for (int i = 0; i < array.length; i++) {
array[i] = String.valueOf(generateRandomLetter(random));
}
System.out.println(Arrays.toString(array));
}
private static char generateRandomLetter(Random random) {
return (char) ('a' + random.nextInt(26));
}
alphabet.charAt(randomInt) would provide you the required random character from alphabet string.
I am making a Java type teacher(to teach typing). I need to generate random words that will be given to type. I made a program to generate random words but it generates just random words without any meaning, but I want to generate real words.
What would be the best way to achieve this?
import java.util.Random;
public class Generator {
private String CHAR_LIST = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private int No_Of_Chars = 2;
public Generator(String CHARS, int No_Of_Char) {
No_Of_Chars = No_Of_Char;
CHAR_LIST = CHARS;
}
public String RandomString() {
String randStr = "";
for (int i = 0; i < No_Of_Chars; i++) {
int number = getRandomNumber();
char ch = CHAR_LIST.charAt(number);
randStr = randStr + ch;
}
return randStr;
}
private int getRandomNumber() {
int randomInt = 0;
Random randomGenerator = new Random();
randomInt = randomGenerator.nextInt(CHAR_LIST.length());
if (randomInt - 1 == -1) {
return randomInt;
} else {
return randomInt - 1;
}
}
}
As other said get a dictionary.
Ask your browser for a word list site. I found this one at the first search : http://www.md5this.com/tools/wordlists.html
Load the file in an ArrayList, a word by element.
Get a random index by int idx = new Random().nextInt(yourArray.size());.
Return the word at that index and remove it String chosenWord = yourArray.remove(idx);
Create a list of words in some text file
Load that text file into your program
Shuffle that list
Use each one in order
(3) is the only step that needs thought: use java.util.Collections#shuffle
Your best option here would be to create a list of words. Next you will randomly pick words from this list for your students to type.
I did the stuff like this but not working. the base48Encode method parameter I have passed the current system time in milli secs
private static final String CHARACTER_SET = "23456789abcdefghijkmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ";
public static String base48Encode(double d) {
Double num = Double.valueOf(d);
Integer length = CHARACTER_SET.length();
String encodeString = new String();
while (num > length) {
encodeString = CHARACTER_SET.charAt(num.intValue() % length) + encodeString;
num = Math.ceil(new Double(num / length) - 1);
}
encodeString = CHARACTER_SET.charAt(num.intValue()) + encodeString;
return encodeString;
}
I won't get duplicate values in any scenario.
It's not possible to 100% guarantee a unique value (especially given a string of 7 characters) due to the Birthday Paradox. Given a character set containing 48 characters, selecting 7 at random, you'd have a 1% chance of collision after only 110,000 random values.
You can help mitigate this by doing two things.
Use a larger character set.
Increase the length of your random value.
Using a character set of 64 characters and selecting 10 at random would greatly decrease your chance of a collision, down to a 1% after 160,000,000 random values.
Rather than using currentTimeMillis to generate a value, which would cause a collision if you generated two values within the same millisecond, I'd suggest just using the Random class (which is seeded from the current time down to the nanosecond).
private static final String CHARACTER_SET = "23456789abcdefghijkmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ";
private static Random rnd = new Random();
public static String randomString(int length){
StringBuilder builder = new StringBuilder();
for(int i = 0; i < length; i++){
builder.append(CHARACTER_SET.charAt(rnd.nextInt(CHARACTER_SET.length())));
}
return builder.toString();
}
I'm making a tool for optimizing script and now I want to compress all names in it to the minimum.
I got the function started for it, but it somehow bugs and stops after length 2 is exceeded.
Is there an easier way to do this? I just need a pattern that generates a String starting from a -> z then aa -> az ba -> bz and so on.
public String getToken() {
String result = ""; int i = 0;
while(i < length){
result = result + charmap.substring(positions[i], positions[i]+1);
positions[length]++;
if (positions[current] >= charmap.length()){
positions[current] = 0;
if ( current < 1 ) {
current++;length++;
}else{
int i2 = current-1;
while( i2 > -1 ){
positions[i2]++;
if(positions[i2] < charmap.length()){
break;
}else if( i2 > 0 ){
positions[i2] = 0;
}else{
positions[i2] = 0;
length++;current++;
}
i2--;
}
}
}
i++;
}
return result;
}
UNLIKE THE OTHER QUESTIONS!! I dont just want to increase an integer, the length increases to much.
Here's one I used
public class AsciiID {
private static final String alphabet=
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
private int currentId;
public String nextId() {
int id = currentId++;
StringBuilder b = new StringBuilder();
do {
b.append(alphabet.charAt(id % alphabet.length()));
} while((id /=alphabet.length()) != 0);
return b.toString();
}
}
I would use a base 36 or base 64 (depending on case sensitivity) library and run it with an integer and before you output, convert the integer to a base 36/64 number. You can think in terms of sequence, which is easier, and the output value is handled by a trusted library.
You can use:
Integer.toString(i++, Character.MAX_RADIX)
It's base36. It will be not as greatly compressed as Base64 but you have a 1-line implementation.
You could search for some library that operates numbers of any radix, say 27, 37 or more. Then you output that number as alphanumeric string (like HEX, but with a-zA-Z0-9).
Well let's assume we can only output ASCII (for unicode this problem gets.. complicated): As a quick look shows its printable characters are in the range [32,126]. So to get the most efficient representation of this problem we have to encode a given integer in base 94 so to speak and add 32 to any generated char.
How you do that? Look up how Sun does it in Integer.toString() and adapt it accordingly. Well it's probably more complex than necessary - just think about how you convert a number into radix 2 and adapt that. In its simplest form that's basically a loop with one division and modulo.
In your tool you need to create a dictionary, which will contain an unique integer id for each unique string and the string itself. When adding strings to the dictionary you increment given id for each newly added unique string. Once dictionary is completed, you can simply convert ids to String using something like this:
static final String CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static final int CHARS_LENGTH = CHARS.length();
public String convert(int id) {
StringBuilder sb = new StringBuilder();
do {
sb.append(CHARS.charAt(id % CHARS_LENGTH));
id = id / CHARS_LENGTH;
} while(id != 0);
return sb.toString();
}
This function generates the Nth Bijective Number (except zeroth). This is the most optimal coding ever possible. (The zeroth would be an empty string.)
If there were 10 possible characters, 0-9, it generates, in order:
10 strings of length 1, from "0" to "9"
10*10 strings of length 2, from "00" to "99"
10*10*10 strings of length 3, from "000" to "999"
etc.
The example uses 93 characters, because I just happened to need those for Json.
private static final char[] ALLOWED_CHARS =
" !#$%&'()*+,-./0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~"
.toCharArray();
private static final AtomicInteger uniqueIdCounter = new AtomicInteger();
public static String getToken() {
int id = uniqueIdCounter.getAndIncrement();
return toBijectiveNumber(id, ALLOWED_CHARS);
}
public static String toBijectiveNumber(int id, char[] allowedChars) {
assert id >= 0;
StringBuilder sb = new StringBuilder(8);
int divisor = 1;
int length = 1;
while (id >= divisor * allowedChars.length) {
divisor *= allowedChars.length;
length++;
id -= divisor;
}
for (int i = 0; i < length; i++) {
sb.append(allowedChars[(id / divisor) % allowedChars.length]);
divisor /= allowedChars.length;
}
return sb.toString();
}