Is there a way to shuffle an array of string in a way that no string is in it's original position? Rotation is not an option
Asked
Active
Viewed 136 times
0
-
1How could you do that if there is only a single String? – Gábor Bakos Feb 06 '14 at 21:32
-
If you move the first string to the end, none of them are in their original position. Would that do? – Paul Hicks Feb 06 '14 at 21:33
-
What if there are two elements in the array "Hilda", and the two get switched? The two objects have been switched but the values are the same. Is that acceptable? – Entity Feb 06 '14 at 21:35
-
No, I want it to be random. The solution has to be different each time and not predictable and rotating is not an option. – streetsoldier Feb 06 '14 at 21:35
-
Do you want every string to *always* be in a different position, or just random? There's a difference. – Entity Feb 06 '14 at 21:37
-
Not necessarily. They don't always have to be in different positions. – streetsoldier Feb 06 '14 at 21:39
-
1This is called a "derangement". You could try searching for "derangement algorithm". – ajb Feb 06 '14 at 21:52
-
See also: http://programmers.stackexchange.com/questions/218255/shuffling-algorithm-with-no-self-mapping – Fred Larson Feb 06 '14 at 22:03
2 Answers
4
You could implement a Fisher-Yates Shuffle, but on each iteration exclude the current position from the random range. This is actually a common mistake that reduces the quality of the shuffle.
EDIT: Reading on, I see that this actually has a name: Sattolo's Algorithm.

Fred Larson
- 60,987
- 18
- 112
- 174
0
This is just one method. I'm sure there are faster or more efficient methods, but this works just fine.
static Random r;
public static String[] shuffle(String[] input)
{
if(r == null) r = new Random();
String[] output = new String[input.length];
ArrayList<Integer> indices = new ArrayList<Integer>();
for(int i = 0; i < input.length; i++) indices.add(i);
for(int i = 0; i < output.length; i++)
{
int randomIndicesIndex = r.nextInt(indices.size());
int randomIndex = indices.get(randomIndicesIndex);
indices.remove(randomIndicesIndex);
output[i] = input[randomIndex];
}
return output;
}
When called in a loop, it outputs this result:
01: Hilda, Quinn, Lyon, Danny, Rob, Clyde, Joe, Jeff, Samantha
02: Hilda, Samantha, Clyde, Danny, Lyon, Joe, Quinn, Rob, Jeff
03: Rob, Samantha, Hilda, Joe, Danny, Jeff, Lyon, Clyde, Quinn
04: Jeff, Lyon, Joe, Quinn, Clyde, Hilda, Rob, Danny, Samantha
05: Danny, Jeff, Hilda, Lyon, Joe, Samantha, Rob, Clyde, Quinn
06: Lyon, Danny, Jeff, Quinn, Rob, Hilda, Clyde, Samantha, Joe
07: Clyde, Hilda, Rob, Samantha, Lyon, Quinn, Danny, Jeff, Joe
08: Clyde, Jeff, Samantha, Danny, Quinn, Hilda, Joe, Lyon, Rob
09: Jeff, Samantha, Danny, Clyde, Rob, Joe, Quinn, Lyon, Hilda
10: Clyde, Samantha, Danny, Lyon, Rob, Hilda, Quinn, Jeff, Joe

Entity
- 7,972
- 21
- 79
- 122
-
-
@user3000837 Maybe! I have no idea though. I'm sure someone has used it before, but it's just how I would solve the problem. It uses slightly more memory (the indices array) to improve the speed. – Entity Feb 06 '14 at 21:51
-
That does not solve the problem. I still some assignments that are in the same place. @TheAdamGaskins – streetsoldier Feb 06 '14 at 23:10
-
@user3000837 You said: `No, I want it to be random.` And `Not necessarily. They don't always have to be in different positions.` This snippet fulfills these requirements. – Entity Feb 07 '14 at 02:23