0

I am attempting to generate a randomized key of letters which are only used once in the overall key. I currently have an array "regKey" which is storing the letters A-Z in its normal order. I would like to create a new array, "newKey" where the order of the letters are completely random but each and every letter is used when creating this new array. There should be no duplicates of any letter in the new array.

So far I've been able to generate a random key but often there are duplicates of certain letters. Here is my code below for reference.

public void keyGen() {
             char [] regKey = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}; 
             char [] newKey = new char [26];

             int tempNum;
             int totalChoice = 26;

             Random rand = new Random();

             for(int i = 0; i<26; i++) {
                 tempNum = rand.nextInt(totalChoice);

                 newKey[i] = regKey[tempNum];

                 System.out.print(newKey[i]);
             }

             String keyString = new String (newKey);

             label_key.setText(keyString);
        }
BipoN
  • 93
  • 8
  • 2
    Does this answer your question? [Random shuffling of an array](https://stackoverflow.com/questions/1519736/random-shuffling-of-an-array) – Joakim Danielson Nov 18 '19 at 14:07
  • 1
    Use a `List` to store the characters and remove the character you used so it won't be available when generating the next one. – daniu Nov 18 '19 at 14:07

3 Answers3

2

What are you trying to do is called "shuffle". You can use Collections.shuffle to "randomize" an array.

List<Character> regKeyAsList = Arrays.asList(regKey);
Collections.shuffle(regKeyAsList);
char[] newKey = regKeyAsList.toArray();
Magus
  • 14,796
  • 3
  • 36
  • 51
1

Assuming you definitely need an Array in the first place, the following code does create the output you desire:

char [] regKey = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}; 
char [] newKey = new char [26];
String[] array = new String(regKey).split("", 0);
ArrayList<String> yourNewArrayList = new ArrayList<String>();
Collections.addAll(yourNewArrayList, array);
Collections.shuffle(yourNewArrayList);
for (int i = 0; i < newKey.length; i++) {
    newKey[i] = yourNewArrayList.remove(0).toCharArray()[0];
}
kopaka
  • 535
  • 4
  • 17
  • 2
    @JoakimDanielson I just provided the whole code for achieving the end result, including the transformation. – kopaka Nov 18 '19 at 14:53
0

Either with Collections.shuffle. Here using Unicode code points.

List<Integer> alphabet = IntStream.rangeClosed('A', 'Z').boxed()
                             .collect(Collection.toList());
// Or enumerate all:
// List<Integer> alphabet = IntStream.of('A', 'B', 'C', ..., 'X', 'Y', 'Z').boxed()
//                              .collect(Collection.toList());
Collections.shuffle(alphabet);
String newKey = new String(alphabet.stream()
        .mapToInt(Integer::intValue)
        .toArray(), 0, alphabet.size());

Or:

         for (int i = 0; i < 26 - 1; i++) {
             int pickedI = i + rand.nextInt(26 - i);

             // Swap i and pickedI:
             int old = newKey[i];
             newKey[i] = regKey[pickedI];
             newKey[pickedI] = old;

             System.out.print(newKey[i]);
         }
Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • 1
    Neither of your answers compiles and if I fix the second one it produces a result with duplicates. – Joakim Danielson Nov 18 '19 at 15:47
  • @JoakimDanielson Appreciate your feedback that I failed here. About the second '(easiest) example: it does not print the last element (i < 26-1) as that needs no randomizing. But if `newKey` is filled by `regKey` with unique entries, swapping two elements will not cause duplicates. – Joop Eggen Nov 19 '19 at 09:48