1

I have created a program that takes a number from a user, and generates, in the amount entered by user, an array of characters with both upper and lower case letters (but no other characters) which must be in random order. In other words, if user enters 5, program generates 5 random lowercase/upper letters, if user enters 25, program generates 25 letters, etc. etc. My program is almost completely successful, except that I cannot get to a good method to generate ONLY upper-or-lowercase letters. It also generates chars 91-96 ( [, \ ,] , ^, _,' ), and I don't want them.

I tried while and if statements to try to remove undesired chars, as well as within the Math.random formula, replace the 58 with 'desiredChars.length,' which has all desired chars, but nothing seems to work.

// Program to generate random chars. 
Scanner sc = new Scanner(System.in);
System.out.println("This program will print an array of random letters based on your specified array size. \nPlease enter your desired array size: ");
int number = sc.nextInt();  
char[] arrayList = new char[number];
int i;
int lowercaseCount = 0;
int uppercaseCount = 0;
// final char[] desiredChars = {'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'z', 'x', 'c', 'v', 'b', 'n', 'm', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'Z', 'X', 'C', 'V', 'B', 'N', 'M'};    


for (i = 0; i < arrayList.length; i++) {
arrayList[i] = (char) ((65 + Math.random()*(58)));
if (Character.isLowerCase(arrayList[i])) {lowercaseCount++;}
if (Character.isUpperCase(arrayList[i])) {uppercaseCount++;}}

System.out.println("Your array with " + number + " random letter(s) is below:\n"+ Arrays.toString(arrayList));
System.out.println("The number of lowercase in your array is " + lowercaseCount);
System.out.println("The number of lowercase in your array is " + uppercaseCount); }}
Anne Bailly
  • 391
  • 3
  • 9
  • A code sample would be useful. – Mansur Jul 18 '19 at 04:26
  • @MensurQulami, I posted my code. I fully meant to post it in my original post, but forgot, and only realized that I didn't post code after posting question. – Anne Bailly Jul 18 '19 at 04:37
  • You can loop until you get your desired character. I mean, if number is between 91-96, then repeat again, until you get something else – Mansur Jul 18 '19 at 04:45
  • `(char) ('A' + (char)(Math.random()*26) + Math.round(Math.random()) * ('a' - 'A'))` – Tibrogargan Jul 18 '19 at 04:46
  • @MensurQulami, I did try to create while loops, but they did not work, as, for example, I added below code, and all it did was put me in some infinite loop of entered a number as a user. while (arrayList[i] >91 && arrayList[i]<97){ continue;} – Anne Bailly Jul 18 '19 at 04:52
  • @AnneBailly, I have provided a code in my answer. – Mansur Jul 18 '19 at 05:00
  • Take a look at this: https://stackoverflow.com/a/41156/2933306 very good answer, example and explanation. – Boris M. Jul 18 '19 at 05:52

3 Answers3

1

You can edit your for loop as follows: looping until getting what you need. We generate a random letter. If it is not in the range we want, then we loop until it is what we want.

Note. My answer theoretically can cause an infinite loop, though the probability is low.

for (i = 0; i < arrayList.length; i++) {
    int randChar = (int) (65 + Math.random() * (58));
    while (randChar >= 91 && randChar <= 96) {
        randChar = (int) (65 + Math.random() * (58));
    }
    arrayList[i] = (char) randChar;
    if (Character.isLowerCase(arrayList[i])) {lowercaseCount++;}
    if (Character.isUpperCase(arrayList[i])) {uppercaseCount++;}
}

@tibrogargan's suggestion's explanation. It is better than looping until what we get. The basic idea is to generate a capital letter first, then randomly adding 0 or 32 to it. Adding 0 will make no changes while adding 32 will make it lowercase. It causes no infinite loop. The following code can be used to generate a random alphabetic character.

char c = (char) ('A' + (char)(Math.random()*26) + Math.round(Math.random()) * ('a' - 'A'));
Mansur
  • 1,661
  • 3
  • 17
  • 41
  • Technically, this code could produce an infinite loop. – Tibrogargan Jul 18 '19 at 05:17
  • Exactly, however that probability is low. – Mansur Jul 18 '19 at 05:18
  • Right, but you're still being deliberately inefficient for no reason. – Tibrogargan Jul 18 '19 at 05:19
  • I am open to any other suggestions. I just modified the requester's code, so that it would work as they expected. The answers provided below are correct, I know. However, those are providing another approach. Mine is editing what's the problem. – Mansur Jul 18 '19 at 05:22
  • That worked!!! Thank you for fixing my faulty loop :). Please let me know if my understanding of what is going on in the fixed code is correct. If an int corresponding to a char in the undesirable range is generated, it triggers another loop for generating random ints. While the undesirable ints are generated, the loop keeps repeating. What breaks the loops are the desired characters generated. Is this correct? – Anne Bailly Jul 18 '19 at 05:23
  • Modify your random to only produce letters. One version in my comment on the question. Here's another: `Random random = new Random(); char c = (char) (random.nextBoolean()?'a':'A') + random.nextInt(26)` (But move the `new Random()` outside the loop). Also, explaining the code would be a bonus – Tibrogargan Jul 18 '19 at 05:27
  • @Tibrogargan, added your suggestion as well, thanks for pointing out. – Mansur Jul 18 '19 at 05:40
  • Don't really want to get pedantic, but the issue is that your answer really is not a good practice. Although it generates the correct answer it needlessly introduces delay. Also, you should explain your answer (not my contribution, lol). Code only answers are not really valuable to the site. – Tibrogargan Jul 18 '19 at 05:43
  • Ah, no problem, since it is on the post, it needs to be explained as well. Plus, actually I had already explained mine with `looping until getting what you need`. Thought that would be enough – Mansur Jul 18 '19 at 05:46
0

First generate a collection of letters.

 private static void appendCharacterRange(List<Character> list, char from, char to) {
    for (char c=from; c<=to; c++){
        list.add(c);
    }
 }

  private static List<Character> getNRandomLetters(int n){
    List<Character> list = new LinkedList<>();
    appendCharacterRange(list, 'a', 'z');
    appendCharacterRange(list, 'A', 'Z');
    Collections.shuffle(list);
    List<Character> result = new LinkedList<>();
    if (n<list.size()){
        return list.subList(0, n);
    }
    for (int i=0; i<=n; i=i+list.size()) {
        result.addAll(list.subList(0, i+result.size()>n?n-result.size():list.size()));
        Collections.shuffle(list);
    }
    return result;
}
Eduard Dubilyer
  • 991
  • 2
  • 10
  • 21
0

Here is one approach, which uses a static string containing all possible characters:

String uppers = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
String all = uppers + uppers.toLowerCase();

int number = sc.nextInt();  
char[] arrayList = new char[number];

Random rand = new Random();

for (int i=0; i < number; ++i) {
    int position = rand.nextInt(all.length());
    arrayList[i] = all.charAt(position);
}

System.out.println(Arrays.toString(arrayList));

For an input of number=10, the following output was generated:

[L, q, s, q, i, U, H, p, u, I]
Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360