Home > Software engineering >  Shuffle a string via swapping content to different index
Shuffle a string via swapping content to different index

Time:10-10

I have an assignment in which we are instructed to create a method which takes a string, scrambles the content of the string, and then returns the scrambled string (ie "Hello" returns "elloH"). However, we are only allowed to do this via loops and basic string functions (no arrays can be used).

My Teacher has left the following suggestion for us:

The best way to shuffle is to generate 2 random numbers (index number) and swap the numbers(the content, not the index) based on the random index numbers. Continue to do it for 100 times, they are shuffled and all characters remain the same but in different positions

How would this nessasarily be done? For reference here is my try at the solution, however it does not work and I'm not sure where to go from here:

public void shuffle(String s1) {
    int i1 = 0;
    int i2 = 0;
    String s2 = "";

    for(int a2 = 0; a2 < s1.length(); a2  ) {
        char c1 = s1.charAt(i1);
        s2  = c1;

        for(int a1 = 0; a1 < 100; a1  ) {
            double d1 = Math.random();
            d1 *= (s1.length()-1);
            i1 = (int) d1; 
        }
    }
    System.out.println(s2);
}

CodePudding user response:

The problem with your code is that you don't swap characters in the String but rather select randomly across the String which causes some characters to be used many times and some not at all.

I would do something like this using StringBuilder that is suitable for String manipulations as long as the String itself is immutable (calling any method from it does not change the former object but returns a new one).

// it's a good practice to delcare formal parameters in a method as final
public void shuffle(final String string) { 
    // store the string length to a variable for sake of comfort
    final int length = string.length();
    // use mutable StringBuilder for easy String manipulations
    final StringBuilder stringBuilder = new StringBuilder(string);
    // initialize the Random object generator once and use many times
    // as you don't want to initialize with each loop and throw it away
    final Random random = new Random();

    // define the number of iterations
    // to repeat as many times as the string is long is more than enough
    for (int i=0; i<length; i  ) {
        // pick two random indices to be swapped
        final int firstIndex = random.nextInt(length);
        final int secondIndex = random.nextInt(length);
        // remember the swapped characters
        // otherwise it would end up in a mess and duplicated characters
        final char firstChar = stringBuilder.charAt(firstIndex);
        final char secondChar = stringBuilder.charAt(secondIndex);
        // perform the swap: basically set the characters to their positions
        stringBuilder.setCharAt(firstIndex, secondChar);
        stringBuilder.setCharAt(secondIndex, firstChar);
    }
    // and see the result
    System.out.println(stringBuilder);
}

Run three times (it looks nicely swapped and the characters remain unchanged):

WoodeHl rl!l
Wer lldooHl!
HW! llrloeod

CodePudding user response:

Hi here is the updated code with your requirement I tried not using the concepts out of string manipulation the swap is not using StringBuilder (that would be the best way to do that but if not needed here as a custom logic to do so)

and also used Math.random() to generate the random number if you want to see all 100 iterations just print the s1 in the for loop.

static String swap(String str, int i, int j) {
    // if both indexes are the same change nothing
    if (i == j)
        return str;
    // if the second index is last then  there will be no substring from j 1 to last;
    if (j == str.length() - 1)
        return str.substring(0, i)   str.charAt(j)   str.substring(1   i, j)   str.charAt(i);
    return str.substring(0, i)   str.charAt(j)   str.substring(1   i, j)   str.charAt(i)
              str.substring(j   1, str.length());
}

public static void shuffle(String s1) {
    // iterate the same logic 100 times
    for (int a1 = 0; a1 < 100; a1  ) {
        // generate 2 random numbers in the range of the length of string
        int randomNumber1 = (int) (Math.random() * s1.length());
        int randomNumber2 = (int) (Math.random() * s1.length());
        // setting the lower random number to randomnumber1 (it is swapping two number without temp)
        if (randomNumber1 > randomNumber2) {
            randomNumber1 = randomNumber1   randomNumber2;
            randomNumber2 = randomNumber1 - randomNumber2;
            randomNumber1 -= randomNumber2;
        }
        // calling the swap method to swap the chars in string.
        s1 = swap(s1, randomNumber1, randomNumber2);
    }
    System.out.println(s1);
}

CodePudding user response:

Since you cannot use arrays, try using StringBuilder.

private String shuffleUtil(String s) {
        final StringBuilder result = new StringBuilder(s);
        for (int rep = 1; rep <= 100; rep  ) {
            final int randomOne = ThreadLocalRandom.current().nextInt(0, s.length());
            final int randomTwo = ThreadLocalRandom.current().nextInt(0, s.length());
            final char c = result.charAt(randomOne);
            result.setCharAt(randomOne, result.charAt(randomTwo));
            result.setCharAt(randomTwo, c);
        }
        return result.toString();
    }

public void shuffle(String s) {
    final String result = shuffleUtil(s);
    System.out.println(s);
}

  • Related