This question already has answers here:
How to generate a random alpha-numeric string
(46 answers)
Closed 6 years ago.
I have an object called Student, and it has studentName, studentId, studentAddress, etc. For the studentId, I have to generate random string consist of seven numeric charaters,
eg.
studentId = getRandomId();
studentId = "1234567" <-- from the random generator.
And I have to make sure that there is no duplicate id.
Generating a random string of characters is easy - just use java.util.Random and a string containing all the characters you want to be available, e.g.
public static String generateString(Random rng, String characters, int length)
{
char[] text = new char[length];
for (int i = 0; i < length; i++)
{
text[i] = characters.charAt(rng.nextInt(characters.length()));
}
return new String(text);
}
Now, for uniqueness you'll need to store the generated strings somewhere. How you do that will really depend on the rest of your application.
This is very nice:
http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/RandomStringUtils.html - something like RandomStringUtils.randomNumeric(7).
There are 10^7 equiprobable (if java.util.Random is not broken) distinct values so uniqueness may be a concern.
You can also use UUID class from java.util package, which returns random uuid of 32bit characters String.
java.util.UUID.randomUUID().toString()
http://java.sun.com/j2se/1.5.0/docs/api/java/util/UUID.html
Random ran = new Random();
int top = 3;
char data = ' ';
String dat = "";
for (int i=0; i<=top; i++) {
data = (char)(ran.nextInt(25)+97);
dat = data + dat;
}
System.out.println(dat);
I think the following class code will help you. It supports multithreading but you can do some improvement like remove sync block and and sync to getRandomId() method.
public class RandomNumberGenerator {
private static final Set<String> generatedNumbers = new HashSet<String>();
public RandomNumberGenerator() {
}
public static void main(String[] args) {
final int maxLength = 7;
final int maxTry = 10;
for (int i = 0; i < 10; i++) {
System.out.println(i + ". studentId=" + RandomNumberGenerator.getRandomId(maxLength, maxTry));
}
}
public static String getRandomId(final int maxLength, final int maxTry) {
final Random random = new Random(System.nanoTime());
final int max = (int) Math.pow(10, maxLength);
final int maxMin = (int) Math.pow(10, maxLength-1);
int i = 0;
boolean unique = false;
int randomId = -1;
while (i < maxTry) {
randomId = random.nextInt(max - maxMin - 1) + maxMin;
synchronized (generatedNumbers) {
if (generatedNumbers.contains(randomId) == false) {
unique = true;
break;
}
}
i++;
}
if (unique == false) {
throw new RuntimeException("Cannot generate unique id!");
}
synchronized (generatedNumbers) {
generatedNumbers.add(String.valueOf(randomId));
}
return String.valueOf(randomId);
}
}
The first question you need to ask is whether you really need the ID to be random. Sometime, sequential IDs are good enough.
Now, if you do need it to be random, we first note a generated sequence of numbers that contain no duplicates can not be called random. :p Now that we get that out of the way, the fastest way to do this is to have a Hashtable or HashMap containing all the IDs already generated. Whenever a new ID is generated, check it against the hashtable, re-generate if the ID already occurs. This will generally work well if the number of students is much less than the range of the IDs. If not, you're in deeper trouble as the probability of needing to regenerate an ID increases, P(generate new ID) = number_of_id_already_generated / number_of_all_possible_ids. In this case, check back the first paragraph (do you need the ID to be random?).
Hope this helps.
Many possibilities...
You know how to generate randomly an integer right?
You can thus generate a char from it... (ex 65 -> A)
It depends what you need, the level of randomness, the security involved... but for a school project i guess getting UUID substring would fit :)
Related
I have participated in coding contest, where I have attempt the given problem, so I am supposed to come up with solution which should not only passing all the test cases, also well optimized in terms of time and space complexity, I have passed 3 out of 7 but I am still not able to identify the rest of the test cases, it is possible that I might be missing something, please help me to rectify the below problem statement.
PROBLEM STATEMENT:
The Powerpuff Girls (100 Marks)
Professor Utonium is restless because of the increasing crime in the world. The number of villains and their activities has increased to a great extent. The current trio of Powerpuff Girls is not well to fight the evils of the whole world. Professor has decided to create the maximum number of Powerpuff Girls with the ingredients he has.
There are N ingredients required in a certain quantity to create a Powerpuff Girl. Professor has all the N ingredients in his laboratory and knows the quantity of each available ingredient. He also knows the quantity of a particular ingredient required to create a Powerpuff Girl. Professor is busy with the preparations and wants to start asap.
The villains, on the other hand, want to destroy the laboratory and stop Professor Utonium from creating more Powerpuff girls. Mojo Jojo is coming prepared with ammunition and Him is leading other villains like Princess, Amoeba Boys, Sedusa, Gangreen Gang etc.
Professor does not have much time as villains will reach the laboratory soon. He is starting the process but does not know the number of Powerpuff Girls which will be created. He needs your help in determining the maximum number of Powerpuff Girls which will be created with the current quantity of ingredients.
Example:
Professor Utonium requires 3 ingredients to make Powerpuff Girls. The 3 ingredients are present in the laboratory in the given quantity:
To make a Powerpuff Girl, Professor Utonium requires:
3 units of Ingredient A
6 units of Ingredient B
10 units of Ingredient C
The maximum number of Powerpuff Girls that can be created is 3 as, after 3, Professor will run out of Ingredient C.
Can you determine the maximum number?
Input Format
The first line of input consists of the number of ingredients, N
The second line of input consists of the N space-separated integers representing the quantity of each ingredient required to create a Powerpuff Girl.
The third line of input consists of the N space-separated integers representing the quantity of each ingredient present in the laboratory.
Constraints
1<= N <=10000000 (1e7)
0<= Quantity_of_ingredient <= LLONG_MAX
Output Format
Print the required output in a separate line.
Sample TestCase 1
Input
4
2 5 6 3
20 40 90 50
Output
8
SOLUTION CODE
package com.mzk.poi;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
public class PowerPuffGirls {
private static final String SPACE = " ";
private static final Integer INITAL_IDX = 0;
private static final Integer LOWER_IDX = 1;
private static final Integer SECOND_IDX = 2;
private static final Integer MAX_LINES = 3;
private static final Integer UPPER_IDX = 1000000;
private static String[] UnitsArr = null;
private static String[] totIngrdientsArr = null;
private static int size = 0;
public static void main(String[] args) {
List<Integer> maxPowerPuffGirlsCreationList = new ArrayList<Integer>();
Scanner stdin = new Scanner(System.in);
String[] input = new String[MAX_LINES];
try {
for (int i = 0; i < input.length; i++) {
input[i] = stdin.nextLine();
if (validateIngredienInput(input[INITAL_IDX])) {
System.exit(INITAL_IDX);
}
}
} finally {
stdin.close();
}
int numOfIngredients = Integer.parseInt(input[INITAL_IDX]);
String units = input[LOWER_IDX];
UnitsArr = units.split(SPACE);
String ingredients = input[SECOND_IDX];
totIngrdientsArr = ingredients.split(SPACE);
size = UnitsArr.length;
int[] specifiedArrayOfUnits = convertToIntegerArray(UnitsArr);
int[] totIngredientInLabArray = convertToIntegerArray(totIngrdientsArr);
for (int i = 0; i < size; i++) {
totIngredientInLabArray[i] = Integer.parseInt(totIngrdientsArr[i]);
}
for (int i = 0; i < numOfIngredients; i++) {
maxPowerPuffGirlsCreationList.add(totIngredientInLabArray[i] / specifiedArrayOfUnits[i]);
}
System.out.println(Collections.min(maxPowerPuffGirlsCreationList));
}
/**
* This method validates the first input
* #param noOfIngredients
* #return boolean
*/
private static boolean validateIngredienInput(String noOfIngredients) {
int numOfIngredients = Integer.parseInt(noOfIngredients);
boolean result = false;
if (numOfIngredients <= LOWER_IDX && numOfIngredients <= UPPER_IDX) {
result = true;
return result;
}
return result;
}
/**
* This utility method convert the String array to Integer array
* #param size
* #param specifiedArrayOfUnits
* #return int[]
*/
private static int[] convertToIntegerArray(String[] arrayToBeParsed) {
int array[] = new int[size];
for (int i = INITAL_IDX; i < size; i++) {
array[i] = Integer.parseInt(arrayToBeParsed[i]);
}
return array;
}
}
The above solution has passed 3 test cases, remaining 7 are un identfied,Please help me to rectify or improve this code.
There are several issues with your code:
try {
for (int i = 0; i < input.length; i++) {
input[i] = stdin.nextLine();
if (validateIngredienInput(input[INITAL_IDX])) {
System.exit(INITAL_IDX);
}
}
} finally {
stdin.close();
}
You don't need to check the first row each time you read one line from the input. Instead you run the test only once. You can run it once you read the first line or after you read the whole input. The code can be look like this:
for (int i = 0; i < input.length; i++) {
input[i] = stdin.nextLine();
}
if (!validateIngredienInput(input[INITAL_IDX])) {
System.exit(...);
}
Also, it is not clear what the return value of validateIngredienInput() means. Is true a correct input or is false? Your if() statements checks for the return value being true and quits if it is.
private static boolean validateIngredienInput(String noOfIngredients)
{
int numOfIngredients = Integer.parseInt(noOfIngredients);
boolean result = false;
if (numOfIngredients <= LOWER_IDX && numOfIngredients <= UPPER_IDX) {
result = true;
return result;
}
return result;
}
Your if() condition doesn't make any sense. You are checking if the number of different ingredients is <= 0 and <= 1. This also means that you could rewrite is as just if (numOfIngredients <= 0). But with the description above it is unclear if the validation should return true or false. Depending on what this method should do it can be written as:
private static boolean validateIngredienInput(String noOfIngredients)
{
int numOfIngredients = Integer.parseInt(noOfIngredients);
return numOfIngredients > 0;
}
This will return true if the value is greater than 0.
UnitsArr = units.split(SPACE);
Variable and field names should begin in lowercase, so they don't get confused with class names, which start in uppercase. It looks like UnitsArr is a class, but it is actually a field. So you should rename your field to unitsArr:
unitsArr = units.split(SPACE);
Also check the requirement/format of the input and the limits:
Constraints
1<= N <=10000000 (1e7)
0<= Quantity_of_ingredient <= LLONG_MAX
As you see the quantity of ingredient can be a long value, but you are using Integer.parseInt() and int[] arrays for storing the quantity. You must change this to long to read long values from the input.
int[] totIngredientInLabArray = convertToIntegerArray(totIngrdientsArr);
for (int i = 0; i < size; i++) {
totIngredientInLabArray[i] = Integer.parseInt(totIngrdientsArr[i]);
}
You are converting the String array to an int array with your helper method convertToIntegerArray(), but then you are doing it again with the for loop. You can skip one of the two.
You might also want to check at: What is a debugger and how can it help me diagnose problems?
I'm making an app where the user has to choose a 4 digit number, and this will be compared to a randomly chosen hidden 4 digit number, but when ever I run the code which should check my array for a comparison between the chosen numbers and the random numbers the 'Arrays.asList().contains())' doesn't seem to pickup on the fact that the array it is checking does have the value it is checking for, any advice?
The code that compares the two variables:-
guess.v1 = code.int1;
guess.v2 = code.int2;
guess.v3 = code.int3;
guess.v4 = code.int4;
int[] guess_list = { guess.v1, guess.v2, guess.v3, guess.v4 };
if (Arrays.asList(guess_list).contains(home.value1)) {
if (code.int1 == home.value1) {
X1.setText("V");
guess.c1 = GuessStatus.V;
} else {
X1.setText("S");
guess.c1 = GuessStatus.S;
}
} else {
X1.setText("X");
guess.c1 = GuessStatus.X;
}
The code that generates the random numbers:-
Code.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent openCode = new Intent(b, code.class);
// adventure_time checks whether there is a saved game already,
// if 1, saved game,
adventure_time = 0;
// random number generation LET THE NUMBER GAMES BEGIN///
Random a1 = new Random();
random1 = new ArrayList<Integer>();
check.fudge = 0;
for (int index = 0; index < 4; index++) {
random1.add(a1.nextInt(5) + 1);
Log.v("MM", "" + random1.get(index));
}
value1 = random1.get(0);
value2 = random1.get(1);
value3 = random1.get(2);
value4 = random1.get(3);
startActivity(openCode);
}
});
You're not calling the Arrays.asList call you think you are. You're actually creating a List<int[]>, not a List<Integer> are you're probably expecting. (There's no such type as List<int> in Java, as it doesn't support generics over primitive types.)
The simplest fix would be to change this:
int[] guess_list = { guess.v1, guess.v2, guess.v3, guess.v4 };
to this:
Integer[] guess_list = { guess.v1, guess.v2, guess.v3, guess.v4 };
You'll then end up creating a List<Integer> which will work appropriately.
Right now I have my array sorting (which is better than getting an error) except it is sorting in the reverse than what I want it to sort in.
public static void sortDatabase(int numRecords, String[] sDeptArr,
int[] iCourseNumArr, int[] iEnrollmentArr)
{
System.out.println("\nSort the database. \n");
String sTemp = null;
int iTemp = 0;
int eTemp = 0;
String a, b = null;
for(int i=0; i<numRecords; i++)
{
int iPosMin = i+1;
for(int j=iPosMin; j<numRecords; j++)
{
a = sDeptArr[i];
b = sDeptArr[iPosMin];
if(a.compareTo(b) > 0)
{
sTemp= sDeptArr[j];
sDeptArr[j] = sDeptArr[iPosMin];
sDeptArr[iPosMin] = sTemp;
iTemp = iCourseNumArr[j];
iCourseNumArr[j] = iCourseNumArr[iPosMin];
iCourseNumArr[iPosMin] = iTemp;
eTemp = iEnrollmentArr[j];
iEnrollmentArr[j] = iEnrollmentArr[iPosMin];
iEnrollmentArr[iPosMin] = eTemp;
}
else if(sDeptArr[j].equals(sDeptArr[iPosMin]) && !(iCourseNumArr[j] < iCourseNumArr[iPosMin]))
{
sTemp= sDeptArr[i];
sDeptArr[i] = sDeptArr[iPosMin];
sDeptArr[iPosMin] = sTemp;
iTemp = iCourseNumArr[i];
iCourseNumArr[i] = iCourseNumArr[iPosMin];
iCourseNumArr[iPosMin] = iTemp;
eTemp = iEnrollmentArr[i];
iEnrollmentArr[i] = iEnrollmentArr[iPosMin];
iEnrollmentArr[iPosMin] = eTemp;
}
else continue;
}
}
}
Again, no array lists or array.sorts. I need just to reverse how this is sorting but I have no idea how.
just do a.compareTo(b) < 0 instead of the > 0
EDIT: I've figured out the problem. But since this is homework (thanks for being honest), I won't post my solution, but here are a few tips:
You are doing selection sort. The algorithm isn't as complicated as you made it. You only have to swap if the two elements you are checking are in the wrong order. I see you have 3 branches there, no need.
Take a look at when you are assigning a and b. Through the inner loop, where j is changing, a and b never change, because i and iPosMin stay the same. I hope that helps.
It's always good to break your algorithm down to discreet parts that you know works by extracting methods. You repeat the same swap code twice, but with different arguments for indices. Take that out and just make a:
-
// swaps the object at position i with position j in all arrays
private static void swap(String[] sDeptArr, int[] iCourseNumArr, int[] iEnrollmentArr, int i, int j)
Then you'll see you're code get a lot cleaner.
First I'd say you need to build a data structure to encapsulate the information in your program. So let's call it Course.
public class Course {
public String department;
public Integer courseNumber;
public Integer enrollment;
}
Why not use the built in sort capabilities of Java?
List<Course> someArray = new ArrayList<Course>();
...
Collections.sort( someArray, new Comparator<Course>() {
public int compare( Course c1, Course c2 ) {
int r = c1.compareTo( c2 );
if( r == 0 ) { /* the strings are the same sort by something else */
/* using Integer instead of int allows us
* to compare the two numbers as objects since Integer implement Comparable
*/
r = c1.courseNumber.compareTo( c2.courseNumber );
}
return r;
}
});
Hope that gets you an A on your homework. Oh and ditch the static Jr. Maybe one day your prof can go over why statics are poor form.
Hmm... I wonder what would happen of you altered the line that reads if(a.compareTo(b) > 0)?
Can someone could be kind and help me out here. Thanks in advance...
My code below outputs the string as duplicates. I don't want to use Sets or ArrayList. I am using java.util.Random. I am trying to write a code that checks if string has already been randomly outputted and if it does, then it won't display. Where I am going wrong and how do I fix this.
public class Worldcountries
{
private static Random nums = new Random();
private static String[] countries =
{
"America", "Candada", "Chile", "Argentina"
};
public static int Dice()
{
return (generator.nums.nextInt(6) + 1);
}
public String randomCounties()
{
String aTemp = " ";
int numOfTimes = Dice();
int dup = 0;
for(int i=0 ; i<numOfTimes; i++)
{
// I think it's in the if statement where I am going wrong.
if (!countries[i].equals(countries[i]))
{
i = i + 1;
}
else
{
dup--;
}
// and maybe here
aTemp = aTemp + countries[nums.nextInt(countries.length)];
aTemp = aTemp + ",";
}
return aTemp;
}
}
So the output I am getting (randomly) is, "America, America, Chile" when it should be "America, Chile".
When do you expect this to be false?
countries[i].equals(countries[i])
Edit:
Here's a skeleton solution. I'll leave filling in the helper methods to you.
public String[] countries;
public boolean contains(String[] arr, String value) {
//return true if value is already in arr, false otherwise
}
public String chooseRandomCountry() {
//chooses a random country from countries
}
//...
int diceRoll = rollDice();
String[] selection = new String[diceRoll];
for ( int i = 0; i < selection.length; i++ ) {
while (true) {
String randomCountry = chooseRandomCountry();
if ( !contains(selection, randomCountry ) {
selection[i] = randomCountry;
break;
}
}
}
//...then build the string here
This doesn't check important things like the number of unique countries.
You need a data structure which allows you to answer the question "does it already contain item X?"
Try the collection API, for example. In your case, a good candidate is either HashSet() or LinkedHashSet() (the latter preserves the insert order).
You'd probably be better of using another structure where you save the strings you have printed. Since you don't want to use a set you could use an array instead. Something like
/*
...
*/
bool[] printed = new bool[countries.length];
for(int i=0 ; i<numOfTimes ; /*noop*/ )
{
int r = nums.nextInt(countries.length);
if (printed[r] == false)
{
i = i + 1;
printed[r] = true;
aTemp = aTemp + countries[r];
aTemp = aTemp + ",";
}
}
return aTemp;
Consider what you're comparing it to:
if (!countries[i].equals(countries[i]))
are you comparing c[i] to c[i]? or c[i] to c[i-1]? Or do you need to check the whole array for a particular string? Perhaps you need a list of countries that get output.
make list uniqueCountries
for each string called country in countries
if country is not in uniqueCountries
add country to uniqueCountries
print each country in uniqueCountries
When you do this, watch out for index out of bounds, and adjust accordingly
Much faster way to do it then using HashSets and other creepy stuff. Takes less code too:
public String randomCounties() {
List<String> results = Arrays.asList(countries);
Collections.shuffle(results);
int numOfTimes = Dice();
String result = " ";
for(int i=0 ; i<numOfTimes; i++) {
result = result + countries[i] + ", ";
}
return result;
}
If you want to avoid outputting duplicate values, you need to record what values have already been listed or remove values from the pool of possibilities when they get selected.
You mention that you do not want to use Sets or ArrayList (I assume you mean Lists in general), I assume that is a requirement of the assignment. If so, you can accomplish this by building arrays and copying data between them the same way that an ArrayList would.
one note, your current implementation chooses between 1 and 6 entries from and array of 4 entries. If you force the selections to be unique you need to decide how to handle the case when you have no more unique selections.
Over the past couple of weeks I've read through the book Error Control Coding: Fundamentals and Applications in order to learn about BCH (Bose, Chaudhuri, Hocquenghem) Codes for an junior programming role at a telecoms company.
This book mostly covers the mathematics and theory behind the subject, but I'm struggling to implement some of the concepts; primarily getting the next n codewords.I have a GUI (implemented through NetBeans, so I won't post the code as the file is huge) that passes a code in order to get the next n numbers:
Generating these numbers is where I am having problems. If I could go through all of these within just the encoding method instead of looping through using the GUI my life would be ten times easier.
This has been driving me crazy for days now as it is easy enough to generate 0000000000 from the input, but I am lost as to where to go from there with my code. What do I then do to generate the next working number?
Any help with generating the above code would be appreciated.
(big edit...) Playing with the code a bit more this seems to work:
import java.util.ArrayList;
import java.util.List;
public class Main
{
public static void main(final String[] argv)
{
final int startValue;
final int iterations;
final List<String> list;
startValue = Integer.parseInt(argv[0]);
iterations = Integer.parseInt(argv[1]);
list = encodeAll(startValue, iterations);
System.out.println(list);
}
private static List<String> encodeAll(final int startValue, final int iterations)
{
final List<String> allEncodings;
allEncodings = new ArrayList<String>();
for(int i = 0; i < iterations; i++)
{
try
{
final int value;
final String str;
final String encoding;
value = i + startValue;
str = String.format("%06d", value);
encoding = encoding(str);
allEncodings.add(encoding);
}
catch(final BadNumberException ex)
{
// do nothing
}
}
return allEncodings;
}
public static String encoding(String str)
throws BadNumberException
{
final int[] digit;
final StringBuilder s;
digit = new int[10];
for(int i = 0; i < 6; i++)
{
digit[i] = Integer.parseInt(String.valueOf(str.charAt(i)));
}
digit[6] = ((4*digit[0])+(10*digit[1])+(9*digit[2])+(2*digit[3])+(digit[4])+(7*digit[5])) % 11;
digit[7] = ((7*digit[0])+(8*digit[1])+(7*digit[2])+(digit[3])+(9*digit[4])+(6*digit[5])) % 11;
digit[8] = ((9*digit[0])+(digit[1])+(7*digit[2])+(8*digit[3])+(7*digit[4])+(7*digit[5])) % 11;
digit[9] = ((digit[0])+(2*digit[1])+(9*digit[2])+(10*digit[3])+(4*digit[4])+(digit[5])) % 11;
// Insert Parity Checking method (Vandermonde Matrix)
s = new StringBuilder();
for(int i = 0; i < 9; i++)
{
s.append(Integer.toString(digit[i]));
}
if(digit[6] == 10 || digit[7] == 10 || digit[8] == 10 || digit[9] == 10)
{
throw new BadNumberException(str);
}
return (s.toString());
}
}
class BadNumberException
extends Exception
{
public BadNumberException(final String str)
{
super(str + " cannot be encoded");
}
}
I prefer throwing the exception rather than returning a special string. In this case I ignore the exception which normally I would say is bad practice, but for this case I think it is what you want.
Hard to tell, if I got your problem, but after reading your question several times, maybe that's what you're looking for:
public List<String> encodeAll() {
List<String> allEncodings = new ArrayList<String>();
for (int i = 0; i < 1000000 ; i++) {
String encoding = encoding(Integer.toString(i));
allEncodings.add(encoding);
}
return allEncodings;
}
There's one flaw in the solution, the toOctalString results are not 0-padded. If that's what you want, I suggest using String.format("<something>", i) in the encoding call.
Update
To use it in your current call, replace a call to encoding(String str) with call to this method. You'll receive an ordered List with all encodings.
I aasumed, you were only interested in octal values - my mistake, now I think you just forgot the encoding for value 000009 in you example and thus removed the irretating octal stuff.