views:

175

answers:

7

I need to create a random string which should be between the length of 6 to 10 but it sometimes generates only about the length of 3 to 5. Here's my code. Can anyone would be able to find out the problem? :(

            int lengthOfName = (int)(Math.random() * 4) + 6;
        String name = "";
        /* randomly choosing a name*/
        for (int j = 0; j <= lengthOfName; j++) {
            int freq = (int)(Math.random() * 100) + 1;
            if(freq <= 6){
                name += "a";
            }if(freq == 7 && freq == 8){
                name += "b";
            }if(freq >= 9 && freq <= 11){
                name += "c";
            }if(freq >= 12 && freq <= 15){
                name += "d";
            }if(freq >= 16 && freq <= 25){
                name += "e";                        
            }if(freq == 26 && freq == 27){
                name += "f";
            }if(freq == 28 && freq == 29){
                name += "g";
            }if(freq >= 30 && freq <= 33){
                name += "h";
            }if(freq >= 34 && freq <= 48){
                name += "i";
            }if(freq == 49 && freq == 50){
                name += "j";
            }if(freq >= 51 && freq <= 55){
                name += "k";
            }if(freq >= 56 && freq <= 60){
                name += "l";
            }if(freq == 61 && freq == 62){
                name += "m";
            }if(freq >= 63 && freq <= 70){
                name += "n";
            }if(freq >= 71 && freq <= 75){
                name += "o";
            }if(freq == 76 && freq == 77){
                name += "p";
            }if(freq == 78){
                name += "q";
            }if(freq >= 79 && freq <= 84){
                name += "r";
            }if(freq == 85 && freq == 86){
                name += "s";
            }if(freq == 87 && freq == 88){
                name += "t";
            }if(freq >= 89 && freq <= 93){
                name += "u";
            }if(freq == 94){
                name += "v";
            }if(freq == 95 && freq == 96){
                name += "w";
            }if(freq == 97){
                name += "x";
            }if(freq == 98 && freq == 99){
                name += "y";
            }if(freq == 100){
                name += "z";
            }
        }
+3  A: 

Conditions like if(freq == X && freq == X+1) are always false.

You probably meant to use || (OR)

Soufiane Hassou
+3  A: 

Your code has a lot of repetitions of the same problem:

if(freq == 28 && freq == 29) { ... }

You are telling Java to follow a condition when freq equals to 28 AND freq equals to 29. It's impossible. You will want to use the OR operator:

if(freq == 28 || freq == 29) { ... }

What's happening now is that when freq equals to any number inside those mistaken conditions, nothing will be added to your string and it will become smaller.

Paulo Guedes
+1  A: 

You seem to have made some typos. On one occasion you write

if(freq == 49 && freq == 50){ name += "j";

which is in fact never true.

Jeff
+9  A: 

I'm sorry but the code is too poorly written to be salvageable. I recommend something like this.

    Random r = new Random(); // just create one and keep it around
    String alphabet = "abcdefghijklmnopqrstuvwxyz";

    final int N = 10;
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < N; i++) {
        sb.append(alphabet.charAt(r.nextInt(alphabet.length())));
    }
    String randomName = sb.toString();

    System.out.println(randomName);

Key points are:

  • Use java.util.Random, specifically nextInt(int n) to get a random int in a given range
    • No need for funky formulas
  • When building a string in a loop, use StringBuilder.
  • Use an alphabet string, and charAt to index its letters.

API links

Related questions


Problems with the original code

There are plenty, unfortunately.

  • String += in a loop yields very poor performance for longer strings
  • for (int j = 0; j <= lengthOfName; j++) is an off-by-one-error
  • freq == 7 && freq == 8 is a logical contradiction
  • It's just unnecessarily verbose!
    • Warning signs should go off whenever you write something like that

I highly recommend doing lots of small but simple exercises to learn Java basics. codingbat.com is great; it has hundreds of these, they're automatically graded so you'll know when your solution works as expected or not. It has sections on logic, strings, arrays, etc.


On uneven letter distribution

The simplest solution is to just have duplicates in the alphabet:

  • String alphabet = "aab"; will have probability for a twice as much as b
  • You can generate the alphabet programmatically from a frequency table
    • I'll leave this as an exercise (or you can ask another question if you need it)
polygenelubricants
Thanks for your code!! but the alphabet is not supposed to be distributed in the same proportion so couldn't think of any better way.... for e.g the alphabet "a" has to be distributed in 6% of chance
Max
@Max, then use a string like "aaaaaabbccc...." (instead of "abcde...") which is of length 100, and use the code above. polygeneL used the word 'like', so I suppose he expected you to do some work :-)
Moron
@Moron, True that. Yeap I'm working on it already!! Thanks for your comment!
Max
Maybe http://stackoverflow.com/questions/2971315/string-stringbuffer-and-stringbuilder/ (Java) is more appropriate? Since 73883 is C# .NET, I agree it is pretty much the same concepts.
Bakkal
Nice answer polygenelubricants! And Moron is no moron.
GregS
+2  A: 

Here is my solution:

import java.util.Random;

Random gen = new Random(474587); //put in random seed
int min = 6;
int max = 10;

// we want 20 random strings 
for(int i=0; i < 20; i++){
 int len = min+gen.nextInt(max-min+1);
 StringBuilder s = new StringBuilder(len);
 while(s.length() < len){
  //97 is ASCII for character 'a', and 26 is number of alphabets
  s.append((char)(97+gen.nextInt(26)));     
 }

System.out.println(s.toString());
}

Sample of output:

zqwloh
jefcso
spcnhxyyk
tzlobaukn
keyxkn
cllhsxybz
ieaudei
bolfzqlxrl
scpfcbztyh
thkfrybffe
nbspabxjh
Bakkal
Woah Thnak you for your code!!
Max
A: 

Just for reference and completeness, here's an "easy" (but less efficient) solution assuming that presence of numbers in the string isn't a big issue:

private static final Random random = new Random();

public static String generateRandomString() {
    return new BigInteger((4 + random.nextInt(3)) * 8, random).toString(36);
}

This generates a random string matching [a-z0-9] of length 6~10 (inclusive).

BalusC
A: 

I bet that you no longer need an answer, but since I've never answered a stack overflow question before, I though this would be a good warm-up problem.

One thing that everyone else seemed to leave out is the frequency aspect of your code. The following code will create 10 random words of length 6 to 10 according to the frequency you wanted:

import java.util.Random;


public class Stuff {
public static void main(String[] args) {

    Random rand = new Random();
    int[] freqs = new int[] {6,8,11,15,25,27,29,33,48,50,55,60,62,70,75,77,78,84,86,88,93,94,96,97,99,100};

    int numWords = 10;
    for(int i = 0; i<numWords; i++)
    {
        String word = "";
        int numLetters = 6 + rand.nextInt(5);
        for(int j = 0; j<numLetters; j++)
        {
            int freq = rand.nextInt(100) + 1;
            int index = 0;
            while(freqs[index] < freq) index++;
            word = word + (char)(97 + index );              
        }
        System.out.println(word);
    }
}

}

Now, my question for you is can you tell me how this works?

JB

John Berryman