i been trying to make a method that shuffles a multiple choice question choices( A, B, C, D) and update the correct answer matching the new order but you cant use array and collections.shuffle.
CodePudding user response:
The algorithm of shuffling may look like this:
- Create two
StringBuilder
instances, one is a copy of the input string, the other is an accumulator of shuffled data. - In the loop, calculate random position in the
copy
, append the character at this position toaccumulator
and remove fromcopy
until copy is not empty
public static String shuffle(String str) {
if (null == str || str.length() < 2) {
return str; // nothing to shuffle, return as is
}
StringBuilder copy = new StringBuilder(str);
StringBuilder acc = new StringBuilder();
Random random = new Random();
while (copy.length() > 0) {
int pos = random.nextInt(copy.length());
acc.append(copy.charAt(pos));
copy.deleteCharAt(pos);
}
return acc.toString();
}
Tests:
for (int i = 0; i < 10; i ) {
System.out.println(i " ABCD -> " shuffle("ABCD"));
}
Output:
0 ABCD -> BDCA
1 ABCD -> BCAD
2 ABCD -> DBCA
3 ABCD -> DCAB
4 ABCD -> BCAD
5 ABCD -> CDBA
6 ABCD -> BACD
7 ABCD -> ACDB
8 ABCD -> ADBC
9 ABCD -> CDAB
A version using List<Character>
to hold a copy and String
instead of StringBuilder
:
public static String shuffle(String str) {
if (null == str || str.length() < 2) {
return str;
}
List<Character> copy = new ArrayList<>();
for (int i = 0; i < str.length(); i ) {
copy.add(str.charAt(i));
}
Random random = new Random();
String result = "";
while (copy.size() > 0) {
int pos = random.nextInt(copy.size());
result = copy.get(pos);
copy.remove(pos);
}
return result;
}
CodePudding user response:
Another one version of a shuffling algorithm:
- Copy all string characters to an intermediate character buffer
- Iterate this buffer and swap each character with an element at a random index
- Create resulting string from that buffer
Java code for this solution:
public static String shuffle(String str, Random random) {
CharBuffer chars = CharBuffer.wrap(str.toCharArray());
for (int i = 0; i < chars.capacity(); i ) {
int index = random.nextInt(chars.capacity());
char tmp = chars.get(index);
chars.put(index, chars.get(i));
chars.put(i, tmp);
}
return chars.toString();
}
P.S. and that's ~10x faster on my machine, than doing this with a StringBuilder or Lists.