4

What is the easiest way to shuffle the letters of a word which is in an array? I have some words in an array and I choose randomly a word but I also want to shuffle the letters of it.

public static void main (String[] args ) {
    String [] animals = { "Dog" , "Cat" , "Dino" } ;    
    Random random = new Random();
    String word = animals [random.nextInt(animals.length)];

    System.out.println ( word ) ;
    //I Simply want to shuffle the letters of word     
}

I am not supposed to use that List thing. I've come up with something like this but with this code it prints random letters it doesn't shuffle. Maybe I can code something like do not print if that letter already printed?

//GET RANDOM LETTER
for (int i = 0; i< word.length(); i++ ) {

char c = (word.charAt(random.nextInt(word.length())));
System.out.print(c); } 
  }
morgothraud
  • 61
  • 1
  • 2
  • 10
  • Show uw what you have tried :) – Dylan Meeus Dec 14 '13 at 22:00
  • 2
    possible duplicate of [How to shuffle characters in a string](http://stackoverflow.com/questions/3316674/how-to-shuffle-characters-in-a-string) – Julián Urbano Dec 14 '13 at 22:06
  • I've already visited that page it uses list and I cannot use it. – morgothraud Dec 14 '13 at 22:07
  • 1
    @user2999672 then add that requirement in your question. Plus, there are some answers there that *don't* use lists – Julián Urbano Dec 14 '13 at 22:07
  • edited. i already checked that post it is not what i am looking for. – morgothraud Dec 14 '13 at 22:12
  • 1
    think again about your shuffle method. you currently print a random character but have no protection against printing the same character each time. you have to remove the characters from the word as you print them. – KevinDTimm Dec 14 '13 at 22:16
  • I don't know how can I delete it. I found something like deleteCharAt but I guess it works with StringBuilder or something. I cannot use that. @KevinDTimm – morgothraud Dec 14 '13 at 22:21
  • What is the "List thing" that you can't use? Do you mean `Collections.shuffle()`? And why the restriction? – gdejohn Dec 14 '13 at 22:42

5 Answers5

10

Really no need for collection and anything more than what follows:

public static void main(String[] args) {

    // Create a random object
    Random r = new Random();

    String word = "Animals";

    System.out.println("Before: " + word );
    word = scramble( r, word );
    System.out.println("After : " + word );
}

public static String scramble( Random random, String inputString )
{
    // Convert your string into a simple char array:
    char a[] = inputString.toCharArray();

    // Scramble the letters using the standard Fisher-Yates shuffle, 
    for( int i=0 ; i<a.length ; i++ )
    {
        int j = random.nextInt(a.length);
        // Swap letters
        char temp = a[i]; a[i] = a[j];  a[j] = temp;
    }       

    return new String( a );
}
Ray Hulha
  • 10,701
  • 5
  • 53
  • 53
Rastikan
  • 517
  • 5
  • 18
  • 1
    Why using `a.length-1` when the condition is `<` rather than using `a.length`. When limiting to `< a.length-1` the last character always stays at the same place. When using `< a.length` and `random.nextInt(a.length)` the last character also gets considered in the shuffle process, however other than that this solution worked a treat! Thanks to @Rastikan – macskay Jan 04 '17 at 23:51
  • I edited the algorithm to also shuffle the last character as per my own test and @mkli90's comment. – Ray Hulha May 05 '17 at 11:26
4

You can use Collections.shuffle :

List<Character> l = new ArrayList<>();
for(char c :  word.toCharArray()) //for each char of the word selectionned, put it in a list
    l.add(c); 
Collections.shuffle(l); //shuffle the list

StringBuilder sb = new StringBuilder(); //now rebuild the word
for(char c : l)
  sb.append(c);

word = sb.toString();

I am not supposed to use that List thing.

Then you can create two StringBuilder objects. One will hold the original word and one will create the shuffled one :

StringBuilder s = new StringBuilder(word);
StringBuilder wordShuffled = new StringBuilder();
while(s.length() != 0){
    int index = random.nextInt(s.length());
    char c = s.charAt(index);
    wordShuffled.append(c);
    s.deleteCharAt(index);
}
System.out.println(wordShuffled.toString());

I found something like deleteCharAt but I guess it works with StringBuilder or something. I cannot use that

Here you can find some nice utilities methods that permits to shuffle an array.

public static char[] shuffleArray(char[] x) {    
       for ( int i = x.length; i > 0; i-- ) {
            int rand = (int)(Math.random()*(i));
            char temp = x[i-1];
            x[i-1] = x[rand];
            x[rand] = temp;
        }
       return x;
}

Then just call this method and use the constructor String(char[] value) :

System.out.println(new String(shuffleArray(word.toCharArray())));

Next time clearly state, what you can use/not use.

Alexis C.
  • 91,686
  • 21
  • 171
  • 177
0

How about something like this?

// Shuffle an array of characters.
public static void shuffleArray(char[] a) {
  int n = a.length; // the length of the array.
  for (int i = 0; i < n; i++) {
    int t = random.nextInt(n); // pick a random number 0 - the length.
    if (t == i) {              // if the random number is the loop counter
      if (i > 0) {             // check if we're at the first element.
        t = random.nextInt(i); // pick another number between 0 - and the loop counter.
      } else {
        t = a.length - 1;      // the end of the loop.
      }
    }
    a[i] ^= a[t];              // swap a[i] and a[t]
    a[t] ^= a[i];
    a[i] ^= a[t];
  }
}

private static Random random = new Random(); // the shared random.

public static void main(String[] args) {
  String[] animals = { "Dog", "Cat", "Dino" };
  String word = animals[random
      .nextInt(animals.length)];

  System.out.println(word);            // the random word.
  char[] arr = word.toCharArray();     // the char[] from the word.
  shuffleArray(arr);                   // shuffle it.
  System.out.println(new String(arr)); // print it.
}
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • This works as I want but can you please explain the swap part because I have no ide what ^= is and why are we swapping 3 times. @Elliott Frisch – morgothraud Dec 14 '13 at 22:28
0

Shuffle String Using Collection.

import java.util.*;

public class ShuffleString {
    
    public static void main(String[] args) {
        
        String str = "Team India Is Best";
        String shuf = "";
        String s1 = str.substring(0, 4);
        String s2 = str.substring(5, 10);
        String s3 = str.substring(11, 13);
        String s4 = str.substring(14, 18);
        ArrayList<String> arr = new ArrayList<String>();
        arr.add(s1);
        arr.add(s2);
        arr.add(s3);
        arr.add(s4);
        Collections.shuffle(arr);

        for(String a : arr)
        {
            shuf += a + " ";
        }
        System.out.println(shuf);
    }
}
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
0

Achieving it by recursion.

public static void main(String[] args) {
    
    Scanner scanner = new Scanner(System.in);
    
    System.out.println("Please enter a string : ");
    String input = scanner.next();
    
    if(input == null || input.length() == 0)
        System.out.println("Invalid String!");
    
    System.out.println("String before scramble : " + input);
    
    System.out.println("String after scramble : " + scramble(input));
}

static String scramble(String input) {
    
    //  if it has only single character simply return it
    if(input.length() == 1)
        return input;
    
    //  get a random number between string's first index and last index 
    int randomIndex = ThreadLocalRandom.current().nextInt(0, input.length());
    
    //  Get the character in that index
    String randomPart = String.valueOf(input.charAt(randomIndex));
    
    //  append that character to the new string and remove it from the source and feed it to same method
    return randomPart + 
            scramble(input.substring(0, randomIndex) + input.substring(randomIndex+1));
}

Output

Please enter a string : 
abcdefg
String before scramble : abcdefg
String after scramble : abdfgce
Arun Sudhakaran
  • 2,167
  • 4
  • 27
  • 52