I'm making an Android App and have currently created some code to be used to generate a code. The generated code will be checked agaisnt the database to see if the code is in use. If it is it will re-generate another code until it finds a code which is not in use. This is done using a do-while loop, whilst there are no codes there will be no noticeable delay to the user. However if there are loads of codes there will be a noticeable delay won't there? The code is below:
public static String generateCode(DBAdapter myDB, String mgrName){
String[] name = mgrName.split(" +");
String fName = name[0];
String lName = name[1];
String fLetter = fName.substring(0, 1).toUpperCase();
String lLetter = lName.substring(0, 3).toUpperCase();
int randomPIN = (int) (Math.random() * 9000) + 1000;
String pin = String.valueOf(randomPIN);
String letters = new StringBuilder().append(fLetter).append(lLetter).append(pin).toString();
Boolean result = checkCode(myDB, letters);
if(result == true){
return(letters);
}
else{
String code = "";
Boolean resultfail = false;
do{
int randomPINFail = (int) (Math.random() * 9000) + 1000;
String generatedCode = new StringBuilder().append(fLetter).append(lLetter).append(randomPINFail).toString();
Boolean check = checkCode(myDB, generatedCode);
if(check){
resultfail = true;
code = generatedCode;
}
}while(!resultfail);
return code;
}
}
public static Boolean checkCode(DBAdapter myDB, String code){
Cursor cursor = myDB.getRowComplaint(code);
if(cursor.getCount() == 0){
return true;
}
else{
return false;
}
}
My Question is what is the chance that the generator will choose a code that is already in use so many times that the user will notice a delay? Bearing in mind the generator will use different manager names as well as different numbers. And is this code safe to use? If not what can be done to make it safe?
EDIT: I can't use UUID as the user has requested the code to contain four letters and four digits. The code is used to retrieve data from the db and that's why it needs to be unique.
As with any performance related question, there's no way for us to answer - you should profile it yourself by creating a large number of existing rows and then seeing how slow it is.
In terms of safety, that's a very broad term and I don't know anything about what you're using these codes for, so I couldn't comfortably tell you that the code is safe. But there don't seem to be any horrible problems with the way you're accessing the database.
Just use UUID class or any other built-in pseudo-random number generator - don't reinvent the wheel. In theory, they will provide such a small collision rate that in absolute most cases you'll generate unique id on a first try. But once again, it depends on your use case. I assume that you're doing something sane and not generating&storing millions of millions of those codes on mobile device.
Be sure to not invoke this routine from the main thread - in this case use might notice the delay even if your DB is empty.
Related
Firstly I am not the greatest with Math, so please excuse any ignorance relating to that. I am trying to maintain probability based randomness across multiple executions but I am failing. I have this input in a JSONObject
{
"option1": 25,
"option2":25,
"option3" :10,
"option4" :40
}
This is my function that selects a value from the above JSONObject based on the probability assigned:
public static String selectRandomoptions(JSONObject options) {
String selectedOption = null;
if (options != null) {
int maxChance = 0;
for (String option : options.keySet()) {
maxChance += options.getInt(option);
}
if (maxChance < 100) {
maxChance = 100;
}
Random r = new Random();
Integer randomValue = r.nextInt(maxChance);
int chance = 0;
for (String option : options.keySet()) {
chance += options.getInt(option);
if (chance >= randomValue) {
selectedOption = options.toLowerCase();
break;
}
}
}
}
the function behaves within a reasonable error margin if I call it x amount of times in a single execution ( tested 100+ calls), the problem is that I am running this every hour to generates some sample data in an event-driven app to verify our analytics process/data but we need it to be somewhat predictable, at least within a reasonable margin?
Has anyone any idea how I might approach this? I would rather not have to persist anything but I am not opposed to it if it makes sense or reduces complexity/time.
The values returned by Random.nextInt() are uniformly distributed, so that shouldn't be a problem.
I you would like to make random results repeatable, then you may want to use Random with seed.
Rather than create a new Random() object each time you want a new random number, just create the Random object once per run, and use the Random.nextInt() object once per run.
Looking at the documentation of Random() constructor,
This constructor sets the seed of the random number generator to a
value very likely to be distinct from any other invocation of this
constructor.it only guarantees it to be different
that's a bit of a weaker contract than the number you get from nextInt().
If you want to get the same sequence of numbers on each run, use the Random(long seed) or the setSeed(long seed) method of the random object. Both these methods set the seed of the generator. If you used the same seed for each invocation it's guaranteed that you will get the same sequence of numbers from the generator.
Random.setSeed(long).
So I've made an app that makes sentences, much like a keyboard of words and pictures, what I'd like to achieve is a kind of predictive text where if a user chooses X they are shown Y and Z, user doesnt want either of these and chooses A.
The next time the user picks X they are shown A, Y and Z, so it learns like your keyboard would, my words are stored in a database and right now i have a crude solution where if the user chooses X they are shown Y and Z, and I also track how many times each card is clicked and show them too but it has no context of full sentences or previously made sentences, i hope this is making sense as I've no idea where to start I've been looking at maybe a hashmap full of essentially TAGS as key value pairs and adding to it but I need to research this, I've also looked at candidate view but that would mean declaring my app as an Input Method I believe and I need the normal keyboard for other things, but I'm not sure how that works or if it's remotely viable so I'm hoping someone can educate me here or point to a better solution.
Below I'll post excerpts of what I'm doing thus far
//Check what card was pressed and update predictedCardActivityDB example
//to carry on like this would mean a lot of typing
//and not a lot of smart results
if (cardsChoice.predictive == true) {
String item = cardWriter.getCardSpeech();
switch(item){
case " I":
String[] I_String = {"LIKE","LOVE","WANT"};
predictedCardActivityDB.prepareCardData
(I_String,getActivity(),prefString);
break;
case " I'm":
String[] Im_String =
{"HAPPY","SAD","ANGRY","HUNGRY","FEELING"};
predictedCardActivityDB.prepareCardData
(Im_String,getActivity(),prefString);
break;
And this is the prepareCardData method excerpt nothing to see here just updates the lists based on the string array
public static void prepareCardData
(String[] predictionArray, Context context ,String prefString){
//boring database stuff
DaoMaster.DevOpenHelper helper =
new DaoMaster.DevOpenHelper(context, "ADD_NEW_CARD", null);
SQLiteDatabase db = helper.getWritableDatabase();
DaoMaster daoMaster = new DaoMaster(db);
DaoSession daoSession = daoMaster.newSession();
addNewCardDao leaseDao = daoSession.getAddNewCardDao();
QueryBuilder qb = leaseDao.queryBuilder()
.orderDesc(addNewCardDao.Properties.Clicked);
QueryBuilder qb2 = leaseDao.queryBuilder()
.orderDesc(addNewCardDao.Properties.Clicked);
predictsList.clear();
String[] strings1 = {"ORIGINAL","SIMPLE","PHOTOS", "USER"};
switch (prefString){
case "PHOTOS":
if (predictionArray != null){
//qb gets any card clicked >2
//qb gets all favourites tagged by a boolean
qb.where(addNewCardDao.Properties.CardIconType.in(strings1),
qb.or(addNewCardDao.Properties.Clicked.ge(2),
addNewCardDao.Properties.Fav.ge(true)));
predictsList = qb.list();
//qb2 gets any card that matches a word from the passed in
//string array predictionArray
qb2 = leaseDao.queryBuilder();
qb2.where(addNewCardDao.Properties.CardIconType.in(strings1),
qb2.or(addNewCardDao.Properties.CardName.in(predictionArray),
addNewCardDao.Properties.CardTitle.in(predictionArray)));
temptList = qb2.list();
db.close();
temptList.addAll(predictsList);
predicts_card_adapter.notifyItemInserted(predictedCardActivityDB.temptList.size());
predicts_card_adapter.notifyDataSetChanged();
predicts_card_adapter = new predictsCardAdapter(temptList,itemTouchListener);
predictsrecyclerView.setAdapter(predicts_card_adapter);
}else{
qb.where(addNewCardDao.Properties.CardIconType.in(strings1),
qb.or(addNewCardDao.Properties.Clicked.ge(2),
addNewCardDao.Properties.Fav.ge(true)));
predictsList = qb.list();
//this should work
predicts_card_adapter.notifyDataSetChanged();
predicts_card_adapter = new predictsCardAdapter(predictsList,itemTouchListener);
predictsrecyclerView.setAdapter(predicts_card_adapter);
db.close();
System.out.println("else, predictsList size " + predictsList.size());
}
break;
}
//should be able t delete this and use the two commented out piecess of code above
//the result being the predicted cards coming first in the list
/*
predicts_card_adapter.notifyItemInserted(predictedCardActivityDB.temptList.size());
predicts_card_adapter.notifyDataSetChanged();
predicts_card_adapter = new predictsCardAdapter(temptList,itemTouchListener);
predictsrecyclerView.setAdapter(predicts_card_adapter);
*/
}
Is it possible to know/get how much space/memory are used when a method is executed or when there is a return value? I don't want to know how much space used by the app, just some code like method or the return value. I tried the runtime.getRuntime, but from my understanding, It looks like it tells me how much space is used by the entire code/app, am I right?
EDIT :
public int [] randtotal(int times2)
{
int in1[] = new int[times2];
for (int i = 0; i<Num2; i++)
Random rand = new Random();
{
in1[times2]= rand.NextInt(5);
}
totalNum(in1);
return int1;
}
As you can see here, at the end of the code there is the "return int1;" , so I want to know when these code is executed how much space is allocated for the value here?
You can use Visualvm tool to profile the overall application and you can also profile certain package, class or function
see this link :
https://visualvm.java.net/profiler.html
During my app development one performance question came to my mind:
I have a lot of lines of data that can looks like that:
!ANG:-0.03,0.14,55.31
!ANG:-0.03,-0.14,305.31
!ANG:-234.03,-0.14,55.31
in general: !ANG:float,float,float
Between those lines there are also "damaged" lines - they don't start with ! or are too short/have extra signs and so on.
To detect lines that are damaged at the begining I simply use
if(myString.charAt(0) != '!')//wrong string
What I can do to detect lines that are damaged at the end? It is very important to mention that I need not only to check if the line is correct but also get those 3 float numbers to use it later.
I've found three options for this:
use regexp
split twice (first ":" and second ",") and count elements
use Scanner class
I am not sure which one of this (or maybe there are other) methods will be the best from the performance point of view. Can you please give me some advice?
EDIT:
After some comments I see that it is worth to write how damage lines an look:
NG:-0.03,0.14,55.31
.14,55.31
!ANG:-0.03,0.14,
!A,-0.02,-0.14,554,-0.12,55
It is quite difficult to talk about number of lines because I am getting them from readings from other device so I get packets of around 20 lines at a time with a frequency of 50Hz.
What I've found out so far is the big drawback of using scanner - for each line I need to create new object and after some time my device is starting to get short on resources.
Benchmark them, then you will know.
The likely fastest way is to write your own tiny state machine to match your format and find the float boundaries. Theoretically a regex will have the same performance, but it's likely to have additional overhead.
As an intermediate solution I'd do something like that :
private static class LineObject {
private float f1, f2, f3;
}
private LineObject parseLine(String line) {
LineObject obj = null;
if (line.startsWith("!ANG:")) {
int i = line.indexOf(',', 5);
if (i != -1) {
int j = line.indexOf(',', i+1);
if (j != -1) {
try {
obj = new LineObject();
obj.f1 = Float.parseFloat(line.substring(5, i));
obj.f2 = Float.parseFloat(line.substring(i+1, j));
obj.f3 = Float.parseFloat(line.substring(++j));
} catch (NumberFormatException e) {
return null;
}
}
}
}
return obj;
}
After you can copy/paste only usefull jdk code of startsWith, indexOf and parseFloat in your own state machine...
I have gone to this site many times and found answers to my questions but its finally time for me to post one of my own! So the objective of a particular class in my software is to generate random passwords of fixed length, comprised of 'low' ASCII characters. The main catch is that I do not want to generate the same password twice but always guarantee uniqueness. Initially I used a HashMap in order to hash each password I had generated so far and use as a check each time I created a new one before returning. However, Java HashMap objects are limited in size and eventually the Map would become too saturated to maintain acceptable retrieval time. The following is my latest crack at the problem:
package gen;
import java.util.Set;
import java.util.Random;
import java.util.HashSet;
public class Generator {
Random r;
int length;
Set<String> seen;
public Generator(int l){
seen = new HashSet<String>();
length = l;
r = new Random();
r.setSeed(System.currentTimeMillis());
}
public String generate(){
String retval = "";
int i = 0;
while(i<length){
int rand = r.nextInt(93)+33;
if(rand!=96){
retval+= (char)rand;
i++;
}
}
return retval;
}
public String generateNoRepeat(){
String retval;
int i;
do{
retval ="";
i = 0;
while(i<length){
int rand = r.nextInt(93)+33;
if(rand!=96){
retval+= (char)rand;
i++;
}
}
}while(!seen.add(retval));
return retval;
}
}
Edit: Thanks so much for the Set suggestion. It makes my code so much cleaner now too!
I may decide to just use the dumb generator method to fill up a BlockingQueue and just multithread it to death...
Further clarification: This is not meant to generate secure passwords. It must simply guarantee that it will eventually generate all possible passwords and only once for a given length and character set.
Note:
I have taken everyone's insight and have come to the conclusion that sequentially generating the possible passwords and storing them to the disk is probably my best option. Either that or simply allow duplicate passwords and supplement the inefficiency with multiple Generator threads.
Why not just encrypt sequential numbers?
Let n be the first number in your sequence (don't start with zero). Let e be some encryption algorithm (e.g. RSA).
Then your passwords are e(n), e(n+1), e(n+2), ...
But I heavily agree with Greg Hewgill and Ted Hopp, avoiding duplicates is more trouble than it is worth.