Reputation: 1364
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
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
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
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
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
Reputation: 1304
To rotate the elements (except the first and last elements) you can use this:
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]);
}
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
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