Rearrange array. Make 1, 3, 5 to 3, 5, 1 and etc - java

Let's say I have an array:
int array[][] = {{1, 2, 3}, {2, 5, 7}, {4, 2, 1}};
How can I randomly make it
int array[][] = {{2, 5, 7}, {1, 2, 3}, {4, 2, 1}};
or
int array[][] = {{4, 2, 1}, {2, 5, 7}, {1, 2, 3},};
And so on.
Is there any JAVA function to help me? Or I have to figure it out by myself?
Thank you.

You might convert your array to a List<int[]> and call Collections.shuffle(). Then convert back to an array.
int array[][] = {{1, 2, 3}, {2, 5, 7}, {4, 2, 1}};
List<int[]> l = Arrays.asList( array ); //the list returned is backed by the array, and thus the array is shuffled in place
Collections.shuffle( l );
//no need to convert back
If you need to keep the original order, you'd have to create a copy of the array (or the list backed by that array), like this:
int array[][] = {{1, 2, 3}, {2, 5, 7}, {4, 2, 1}};
List<int[]> l = new ArrayList<int[]>( Arrays.asList( array ) ); //creates an independent copy of the list
Collections.shuffle( l );
int newArray[][] = l.toArray( new int[0][0] );
Another way:
int array[][] = {{1, 2, 3}, {2, 5, 7}, {4, 2, 1}};
int newArray[][] = array.clone(); //copy the array direcly
List<int[]> l = Arrays.asList( newArray );
Collections.shuffle( l );

It is very simple using the Collections.shuffle(..) method as the Arrays.asList(..) method returns a List backed by the array.
Collections.shuffle(Arrays.asList(array));
Full example:
public static void main(String... args) {
int array[][] = {{1, 2, 3}, {2, 5, 7}, {4, 2, 1}};
Collections.shuffle(Arrays.asList(array));
for (int[] a : array)
System.out.println(Arrays.toString(a));
}

If you can use collections there is a shuffle method, if you have to use a primitive type such as int, you will have to shuffle it yourself. Here are examples of both:
http://blog.ryanrampersad.com/2008/10/13/shuffle-an-array-in-java/

Try the Collections class that comes with Java. You can use the shuffle() method to randomize the indices to access the arrays.
Link to Java API

Use Collections:
something like this:
List<int[]> list = Arrays.asList(array);
Collections.shuffle(list);
int[][] shuffledArray = (int[][]) shuffledList.toArray();

What you want is random swaps of the contents of the outer array.
You could use java.Random's nextBoolean() to get a true/false as to whether to make a swap, such as between 1&2 or 1&3 or 2&3.
This is assuming you want to work with the primitive types, and not classes.

Related

Use Arrays when initializing another Array at specific position

I have an integer array.
int[] arr1 = new int[] {3, 4, 5};. I want to insert this array when initializing another array. So that when
int[] arr2 = new int[] {8, 7, arr1, 1, 0};, arr2 will equal {8, 7, 3, 4, 5, 1, 0}.
Also, I do not know the length of arr1, so I can't do int[] arr2 = new int[] {8, 7, arr1[0], arr1[1], arr1[2], 1, 0};
Any help is greatly appreciated.
Sadly as far as I'm aware something like that can't be done in a single operation. The best I was able to come up with is to create a result array. Then you copy to it first part of arr2, whole arr1 and finally second part of arr2. In the end whole method would look like so:
private static int[] insertArrayAtPosition(int[] arr1, int[] arr2, int insertPos){
int[] result = new int[arr1.length + arr2.length];
System.arraycopy(arr2, 0, result, 0, insertPos);
System.arraycopy(arr1, 0, result, insertPos, arr1.length);
System.arraycopy(arr2, insertPos, result, insertPos + arr1.length, arr2.length - insertPos);
return result;
}
And then you can call it like so:
public static void main(String args[]) {
int[] arr1 = new int[] {3, 4, 5};
int[] arr2 = new int[] {8, 7, 1, 0};
int[] result = insertArrayAtPosition(arr1, arr2, 2);
System.out.println(Arrays.toString(result));
}
Edit: Milgo's solution looks much better. However, mine allows to insert one array into another at specific position after they are already created. Which one to use depeds on the usecase.
You could use ArrayUtils.addAll() three times.
int[] arr1 = new int[] {3, 4, 5};
int[] arr2 = new int[arr1.length + 4];
ArrayUtils.addAll(arr2, new int[]{8, 7});
ArrayUtils.addAll(arr2, arr1);
ArrayUtils.addAll(arr2, new int[]{1, 0});
ArrayUtils is part of Apache Commons.
This is not natively supported in java / there is no language feature that allows you to use a one liner.
You can of course write a loop that inserts the elements of the other array, you can also use list interfaces or Arrays#stream. The best way to do it should probably be to use lists, like this:
List<Integer> arr1 = Arrays.asList(3, 4, 5);
List<Integer> arr2 = Arrays.asList(8, 7, 1, 0);
arr2.addAll(2, arr1);
Hope this helpes.
Edit: It is a one liner btw :)

Is the 2D array defined in java? If yes then what will be the output?

public class Main {
public static void main(String[] args) {
int[][] numbers = {{1, 2, 3} , {4, 5, 6, 7}}; //Is it defined?
int x = numbers[0][3]; // Should the output be 0?
System.out.println(x);
}
}
you may take a look here into the official oracle specification:
https://docs.oracle.com/javase/specs/jls/se7/html/jls-10.html
When you take a look on chapter (array access) you will see that:
"All arrays are 0-origin. An array with length n can be indexed by the integers 0 to n-1."
A 2D array is really an array of arrays. So you can do this.
int[][] arr = new int[4][];
arr[0] = new int[] {1,2,3};
arr[1] = new int[] {4,5,6,7};
arr[2] = new int[] {8,9,10,11,12,13};
arr[3] = new int[] {14,15};
And to print them.
for (int[] a : arr) {
System.out.println(Arrays.toString(a));
}
Prints
[1, 2, 3]
[4, 5, 6, 7]
[8, 9, 10, 11, 12, 13]
[14, 15]
Technically, there are no two-dimensional arrays. What you can have is an array of arrays; this is conveyed precisely by the [][] syntax.
In your example,
int[][] numbers = {{1, 2, 3} , {4, 5, 6, 7}};
the 0'th element of numbers, i.e., numbers[0], is a 3-element array, whereas numbers[1], is a 4-element array.
Accessing numbers[0][3] will raise an exception, since 3 is out of bounds for the 3-element array.
Reference to Java Language Specification: Chapter 10, Arrays.

How to convert List of int array to 2D Array?

Given a list of int[] [{7, 0}, {7, 1}, {6, 1}, {5, 0}, {5, 2}, {4, 4}] I need to convert it into 2D Array {{7, 0}, {7, 1}, {6, 1}, {5, 0}, {5, 2}, {4, 4}} using Java 8.
Before Java 8 we could use the following logic: temp is List<int[]> which contains above list of elements. First res[][] is created of the same size as a List of elements in temp.
int[][] res = new int[temp.size()][2];
for (int i = 0; i < temp.size(); i++) {
res[i][0] = temp.get(i)[0];
res[i][1] = temp.get(i)[1];
}
Try this.
List<int[]> list = List.of(
new int[] {7, 0}, new int[] {7, 1},
new int[] {6, 1}, new int[] {5, 0},
new int[] {5, 2}, new int[] {4, 4});
int[][] res = list.stream().toArray(int[][]::new);
System.out.println(Arrays.deepToString(res));
result
[[7, 0], [7, 1], [6, 1], [5, 0], [5, 2], [4, 4]]
See this code run live at IdeOne.com.

Flatmapping a 2D array by column rather than row in Java

Given the following two dimensional array
int[][] arr = {{1, 2}, {3, 4}, {5, 6}};
How can I flatten it column-by-column using the Java 8 Stream API? I want to get:
int[] result = {1, 3, 5, 2, 4, 6};
I tried doing a simple flatMap, but this flattens row-by-row and results in the wrong order:
// result is { 1, 2, 3, 4, 5, 6 }
int[] result = Arrays.stream(arr)
.flatMapToInt(Arrays::stream)
.toArray();
I considered transposing the array first so that I can use the above snippet, but creating an intermediate, transposed copy of the array seems unnecessary. How can I flatmap by column directly?
It can be assumed that all the nested arrays are of same length.
You can stream the inner indexes and flatMap to each outer array:
IntStream.range(0, arr[0].length)
.flatMap(i -> Arrays.stream(arr).mapToInt(a -> a[i]))
.toArray()
If we assume that all the nested arrays are of the same length we can use nested loops:
int[][] arr = {{1, 2}, {3, 4}, {5, 6}};
int[] res = new int[arr.length * arr[0].length];
int j = 0;
for (int i = 0; i < arr[0].length; i++) {
for (int[] a : arr) {
res[j++] = a[i];
}
}
System.out.println(Arrays.toString(res)); // [1, 3, 5, 2, 4, 6]
This is another way to do it:
int[][] nestedArray = {{1, 12, 2}, {1, 13, 11, 5, 16}, {7, 8, 9}};
LinkedList<Integer> theList = new LinkedList<>();
for(int[] sList: nestedArray) {
stream(sList)
.forEach(theList::add);
}
theList.stream()
.forEach(e ->System.out.println(e));
I revised the previous code to more KISS and readable.
int[][] nestedArray = {{3, 4, 5, 6}, {1, 2}, {7, 8, 9}};
LinkedList<Integer> theList = new LinkedList<>();
for(int[] sList: nestedArray) {
stream(sList)
.forEach(theList::add);
}
theList.stream()
.forEach(e ->System.out.println(e));

Double Array: Out of Bounds

I am trying to write a code that finds the average of the inputs of a 2D array:
This is what I have written:
public class AverageLength
{
public static void main(String[] args)
{
int sum = 0;
int w = 0;
int[][] foobar = new int[][]
{
{0, 5, 7},
{3, 2, 4},
{8, 7, 3},
{1, 5, 3}
};
for (int i = 0; i < foobar.length; i++)
{
for (int j = 0; j <foobar[0].length; j++)
{
System.out.println(foobar[i][j]);
sum = sum + foobar[i][j];
w++;
}
} System.out.println("Average = " + sum/w);
}
}
However, if I change the array lengths and try what follows:
int[][] foobar = new int[][]
{
{0, 5, 7, 3},
{3, 3, 5, 7, 8, 4},
{8, 3},
{1, 5, 1, 2, 3}
};
it gives me the following error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2
at AverageLength.main(AverageLength.java:18)
How can I fix this issue?
change
foobar[0].length
to
foobar[i].length
when your sub arrays lengths are different you should get corresponding length
for example
{0, 5, 7, 3},
{3, 3, 5, 7, 8, 4},
{8, 3},
in this case
foobar[0].length is 4 .so when you loop through 3rd sub array {8, 3}
and when you try to access 2nd index [3rd element ] you get error
ArrayIndexOutOfBoundsException: 2
because there is no 2nd index.
and also in 2nd sub array {3, 3, 5, 7, 8, 4}, value 8 and 4 will not print because you loop 4 times .
When you check in your seccond for for array length you should use i not 0, because if you use 0 you will always get length of just first array.
for (int j = 0; j <foobar[i].length; j++)
By using foobar[0].length you are using the length of the first inner array for every inner array. Use foobar[i].length instead, which will calculate the current array's length.
By the way: Calculating averages of int arrays can be done java-internally since Java8. An example of how to use Java8's streaming API to solve this task:
import java.util.Arrays;
public class AverageLength
{
public static void main(String[] args)
{
int[][] foobar = new int[][]
{
{0, 5, 7},
{3, 2, 4},
{8, 7, 3},
{1, 5, 3}
};
System.out.print("Average = ");
System.out.println(
// convert 2D array to stream of arrays
Arrays.stream(foobar)
// flatten 2D array to 1D array
.flatMapToInt(Arrays::stream)
// let java calculate the average
.average()
// get result
.getAsDouble());
}
}
Benefits:
code is easier to understand
your program is potentially much faster
code can be easily changed to run in several threads (use .parallel())

Categories