nTuply
nTuply

Reputation: 1364

How to rotate a String of space delimited integers in Java?

Suppose I have the following String: "10 30 20 12 34". Now I want to rotate the String but keep the first and last integers fixed. So I should get the 3 outputs should be as follows:

10 20 30 12 34

10 30 12 20 34

10 12 20 30 34

Now, I am trying to first convert the String into an int[] array such that it looks like [10, 30,20, 12, 34] and then create another array, get each element of the original array and insert them in the new array.

This is what I have so far:

String[] arr1 = tree.getPreOrder().split(" ");
int[] arr2 = new int[5];
arr2[0] = Integer.parseInt(arr1[0]);
arr2[1] = Integer.parseInt(arr1[3]);
arr2[2] = Integer.parseInt(arr1[2]);
arr2[3] = Integer.parseInt(arr1[1]);
arr2[4] = Integer.parseInt(arr1[4]);

My issue is, how do I now convert arr2 into the format 10 12 20 30 34. I tried to use join() but it doesn't work.

Also, is there a simpler way to do what I'm trying to do as currently, I am hard coding those values.

Thanks

UPDATE I created a method which basically rotates the middle values now. However, I got into an issue where one randomly generated String was the same as the original and I would like to avoid that. I'm basically trying to generate only exactly 3 variations of the original string if that helps. Here's my updated code:

static String randomizeAnswer(String ans) {
    String[] arr = ans.split(" ");

    int arraySize = arr.length;

    String firstElement = arr[0];
    String lastElement = arr[arraySize - 1];

    String[] arr2 = new String[arraySize - 2];

    String arr3[] = new String[arraySize];

    arr3[0] = firstElement;
    for (int i = 0; i < arraySize - 2; i++) {
        arr2[i] = arr[i + 1];
    }

    Collections.shuffle(Arrays.asList(arr2));

    for (int j = 0; j < arr2.length; j++) {
        arr3[j + 1] = arr2[j];
    }
    arr3[arraySize - 1] = lastElement;

    return String.join(" ", arr3);
}

for int(i = 0; i<3; i++){
    System.out.println(randomizeAnswer("10 30 20 12 34"));
}

UPDATE 2 I eventually managed to make a solution which works but the answer by @WJS below is much better.

static String randomizeAnswer(String ans) {
        String[] arr = ans.split(" ");

        int arraySize = arr.length;

        String firstElement = arr[0];
        String lastElement = arr[arraySize - 1];

        String[] arr2 = new String[arraySize - 2];

        String arr3[] = new String[arraySize];

        arr3[0] = firstElement;
        for (int i = 0; i < arraySize - 2; i++) {
            arr2[i] = arr[i + 1];
        }

        Collections.shuffle(Arrays.asList(arr2));

        for (int j = 0; j < arr2.length; j++) {
            arr3[j + 1] = arr2[j];
        }
        arr3[arraySize - 1] = lastElement;

        return String.join(" ", arr3);
        
    }

    static String[] generateAnswers(String ans) {
        String[] answers = new String[5];
        answers[0] = ans;
        answers[4] = "None of the answers are correct";

        for (int x = 0; x < 3; x++) {

            while (true) {
                String randomAns = randomizeAnswer(ans);
                if (Arrays.stream(answers).anyMatch(randomAns::equals)) {
                    continue;
                } else {
                    answers[x+1] = randomAns;
                    break;
                }
            }
        }

        return answers;
    }

Upvotes: 0

Views: 224

Answers (6)

MC Emperor
MC Emperor

Reputation: 23017

Here's my two cents using Java Streams.

private static int[] rotate(int[] array, int count) {
    if (array.length >= 0 && array.length <= 2) {
        return array;
    }

    return IntStream.range(0, array.length)
        .map(i -> (i == 0 || i == array.length - 1) ? i : (i - 1 + count) % (array.length - 2) + 1)
        .map(i -> array[i])
        .toArray();
}

This rotates the given array count positions to the right, but leaves the first and last indexes unharmed. For example, when count = 1, the array [10, 30, 20, 12, 34] becomes [10, 12, 30, 20, 34].


If you want to generate an n number of random sequences, you could use the snippet below. This generates arrays which are not equal to the original array.

int array = { … };
int n = 2;
ThreadLocalRandom.current().ints(n, 1, array.length - 2)
    .mapToObj(randomInt -> rotate(array, randomInt))
    .forEach(result -> System.out.println(Arrays.toString(result)));
    // Or, if you want to convert it back to a String:
    //.collect(Collectors.mapping(String::valueOf, Collectors.joining(" ")));

Collections::shuffle

Of course, you can also simply shuffle the elements minus the first and last ones using Collections::shuffle and List::subList. This method is generic, so it really does not matter whether the elements are actually integers or not. For instance, a List<String> is yielded with Arrays.asList("10 30 20 12 34".split(" ")).

public static <T> List<T> shuffleMid(List<T> list) {
    List<T> newList = new ArrayList<>(list);
    do {
        Collections.shuffle(newList.subList(1, newList.size() - 1));
    } while (newList.equals(list)); // Make sure it is unequal to the original
    return newList;
}

The do-while loop makes sure the shuffled list is not equal to the original list. This may be a naive implementation.

Upvotes: 1

Idle_Mind
Idle_Mind

Reputation: 39142

Another example:

  public static void main(String[] args) {
    String treePreOrder = "10 30 20 12 34";    
    String rot1 = rotateMiddle(treePreOrder);
    String rot2 = rotateMiddle(rot1);

    System.out.println(treePreOrder);
    System.out.println(rot1);
    System.out.println(rot2);
  }

  public static String rotateMiddle(String values) {
    String[] arr = values.split(" ");
    if (arr.length >= 4) {
      String temp = arr[1];
      for(int i=1; i<=(arr.length-3); i++) {
        arr[i] = arr[i+1];
      }
      arr[arr.length-2] = temp;
    }
    return String.join(" ", arr);
  }

Output:

10 30 20 12 34
10 20 12 30 34
10 12 30 20 34

Upvotes: 1

user14410324
user14410324

Reputation:

There most definitely is a better way to leverage other APIs in the JDK... but here is what I came up with.

// shifts by [direction] spaces (-ve and +ve) for left/right. So far so good with not throwing IndexOutOfBoundsExceptions :)
private static int[] shift(int[] values, int direction) {

    int[] result = new int[values.length];
    for (int i = 0; i < result.length; i++) {
        result[i] = values[(values.length + (i + direction % values.length)) % values.length];
    }
    return result;
}

public static void main(String[] args) {
    int[] values = new int[]{101, 1, 2, 3, 100};
    int[] middleValues = Arrays.copyOfRange(values, 1, values.length-1);
    
    int[][] allCombos = new int[middleValues.length][values.length];
    
    int shiftPtr = 0;
    for (int[] row : allCombos) {
        row[0] = values[0];
        row[row.length-1] = values[values.length-1];
        int[] shifted = shift(middleValues, shiftPtr);
        for (int i = 0; i < middleValues.length; i++) {
            row[i + 1] = shifted[i];                
        }
        shiftPtr++;
        // and print out to test...
        System.out.println(Arrays.toString(row));
    }                                                
    
}

And you end up with this output....

> [101, 1, 2, 3, 100]  
> [101, 2, 3, 1, 100]
> [101, 3, 1, 2, 100]

Upvotes: 0

WJS
WJS

Reputation: 40062

Convert the array to ints. Note that the string values could be rotated without parsing to an int.

String str = "10 30 20 12 34";

int[] vals = Arrays.stream(str.split("\\s+"))
        .mapToInt(Integer::parseInt).toArray();

The range to rotate

int start = 1;
int end = 4; // exclusive

An array to save the rotated array of values.

String[] results = new String[end - start];

And now rotating them, converting to a string and storing. Note that the previously rotated array needs to be fed back into the method. But that array is not changed because it is copied in the rotate method.

for (int i = 0; i < end - start; i++) {
    vals = rotate(vals, start, end);
    // convert to String - can't use join since these are not strings.
    // this just streams the results, converts to a string, and joins them into
    // a single string.
    results[i] =
            Arrays.stream(vals).mapToObj(v -> Integer.toString(v))
                    .collect(Collectors.joining(" "));
}

for (String rotated : results) {
    System.out.println(rotated);
}

prints

10 20 12 30 34
10 12 30 20 34
10 30 20 12 34

This simply rotates the array one cell to the left within the specified range. It first makes a copy of the original array. Note the end is exclusive.

public static int[] rotate(int[] arr, int start, int end) {
    arr = Arrays.copyOf(arr, arr.length);
    int v = arr[start];
    for (int i = start; i < end-1; i++) {
      arr[i] = arr[i+1];
    }
    arr[end-1] = v;
    return arr;
}

Upvotes: 1

ibra
ibra

Reputation: 1304

To rotate the elements (except the first and last elements) you can use this:

    1. use another helping array:
        String in = "10 30 20 12 34";
        String[] arr_in = in.split(" ");
        String[] arr_out = new String[arr_in.length];
        
        arr_out[0] = arr_in[0];
        arr_out[arr_out.length-1] = arr_in[arr_in.length-1];
        
        for(int i=arr_in.length-2, j=1;  i>0;  i--,j++)
        {
            arr_out[j] = arr_in[i];
        }
        
        // print:
        for(int i=0; i<arr_out.length;i++)
        {
            System.out.println(arr_out[i]);
        }
    1. in place :
    
    public static void main(String[] args) {
        
        String in = "10 30 20 12 34";
        String[] arr = in.split(" ");
        
        String tmp;
        for(int i=arr_in.length-2, j=1;  i>(arr_in.length/2);   i--,j++)
        {
            tmp = arr[i];
            arr[i] = arr[j];
            arr[j] = tmp;
        }
        
        // print:
        for(int i=0; i<arr.length;i++)
        {
            System.out.println(arr[i]);
        }
        
        
    }

Upvotes: 0

ABC
ABC

Reputation: 655

    String[] array = new String[5];
    for(int i = 0; i < 5; i++)
        array[i] = i + 1 + "";
     //array[0] = 1, array[1] = 2, array[3] = 3, array[4] = 4, array[5] = 5

    int first = 0;
    int last = array.length - 1;
    
    for(int i = 1; i < array.length / 2; i++){
        first = i;
        last = array.length - i - 1;
        String aux = array[first];
        array[first] = array[last];
        array[last] = aux;
        first++;
        last--;
    }
    
    for(int i = 0; i < array.length; i++)
        System.out.print(array[i] + " ");

The output will be: 1 4 3 2 5

Upvotes: 0

Related Questions