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())
Related
I'm trying to slice the columns or rows of a 2d Integer Array in Java.
I tried the following syntax array[:][0] or array[0][:] to get the first column/row. I get an error, so most probably this is not the correct syntax in Java. Is it possible to slice in any case a specific column/row in Java?
If I'm not mistaken, slicing in Python corresponds to extracting a subarray from the given array, so if you have an array like below:
int[][] vet = new int[][]{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
Performing the following slicing vet[0:3][1] corresponds to retrieve an array with the elements 2, 5, 8 (second column from row 0 included to row 3 excluded).
Unfortunately, in Java this is not possible, at least not "vertically" since a 2D array is basically an array of arrays. Each "row" index identifies a sub-array but in reality there are now actual rows or columns, just arrays within another array.
What you could do is to use the Arrays.copyOfRange() method to slice an array "horizontally".
Integer[][] vet = new Integer[][]{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
Integer[] subArray = new Integer[3];
subArray = Arrays.copyOfRange(vet[1], 0, 3); //Retrieves the elements [4, 5, 6]
Instead, for slicing "vertically" you need to write a utility method:
public static void main(String[] args) {
Integer[][] vet = new Integer[][]{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
Integer[] subArray = new Integer[3];
verticalSlicing(vet, subArray, 1, 0, 3);
System.out.println(Arrays.toString(subArrayVert)); //Prints [2, 5, 8]
}
public static <T> void verticalSlicing(T[][] vet, T[] subArray, int col, int rowStart, int rowEnd) {
if (col < 0 || col > subArray.length || (rowEnd - rowStart) > subArray.length) {
return;
}
IntStream.range(rowStart, rowEnd).forEach(i -> subArray[i] = vet[i][col]);
}
Usually a 2d array in java will look something like this:
double[][] doubleArray = new double[3][4];
So getting the first row can be:
double[] firstRow = doubleArray[0];
And getting the first column can look like this:
double[] firstColumn = new double[doubleArray.length];
for (int i = 0; i < doubleArray.length; i++) {
firstColumn[i] = doubleArray[i][0];
}
Given that you index array[x][y] you can get column x by:
int column[] = array[x].
To get row y:
int row[] = new int[array.length];
for (int i = 0; i < array.length; i++) {
row[i] = array[i][y];
}
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));
I am creating a program with a method whose input is an 2D array of int, that checks to see if arrays are Latin Squares.
For example a Latin Square would look like this:
1 2 3
2 3 1
3 1 2
This is my code so far:
public class LatinSquare {
public boolean isLatinSquare(int[][] a){
int[] row= new int[a.length];
int[] column = new int[a[0].length];
for (int j = 0; j<column.length; j++){
for (int i = 0; i<row.length;i++){
row[i] = a[i][j];
}
for (int i = 0; i<row.length -1; i++){
for (int x= i+1; x<=row.length;x++){
if (row[i]==row[x])
return false;
}
}
}
}
The code is not fully complete but I just wanted to know if someone could answer some questions before I head in the wrong direction if I am doing something wrong.
My Question: Is this the best approach for checking arrays to see if they would fulfill a Latin Square? My thought process is that I start at column '0' and then go through the row comparing each number to each other making sure they are not equal, and move through each column this way. Is this the wrong way to be approaching this?
Lots of nested loops will degrade performance. Here is a faster version, but it uses a bit more memory.
It relies on the values of the square being in the range 1 to N, where N is the square size.
private static boolean isLatinSquare(int[][] square) {
boolean[][] foundInRow = new boolean[square.length][square.length];
boolean[][] foundInCol = new boolean[square.length][square.length];
for (int row = 0; row < square.length; row++) {
if (square[row].length != square.length)
return false; // Not a square
for (int col = 0; col < square.length; col++) {
int idx = square[row][col] - 1;
if (foundInRow[row][idx] || foundInCol[col][idx])
return false;
foundInRow[row][idx] = foundInCol[col][idx] = true;
}
}
return true;
}
Test
System.out.println(isLatinSquare(new int[][] { {1, 2, 3},
{2, 3, 1},
{3, 1, 2} }));
System.out.println(isLatinSquare(new int[][] { {1, 2, 3},
{3, 1, 2},
{2, 3, 1} }));
System.out.println(isLatinSquare(new int[][] { {1, 3, 2},
{2, 1, 3},
{3, 2, 1} }));
System.out.println(isLatinSquare(new int[][] { {1, 3, 2},
{3, 2, 1},
{2, 1, 3} }));
System.out.println(isLatinSquare(new int[][] { {1, 3, 2},
{3, 2, 1},
{1, 3, 2} }));
System.out.println(isLatinSquare(new int[][] { {1, 3, 1},
{3, 2, 3},
{2, 1, 2} }));
System.out.println(isLatinSquare(new int[][] { {1, 2, 3},
{2, 3},
{3, 1, 2} }));
Output
true
true
true
true
false
false
false
If I have an array:
int[] myArray = new int[10]
for (int i = 0; i < myArray.length; i++) {
myArray[i] = i;
}
//resulting array: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
How can I move everything behing the 4 up one space, and send the 4 to the back? Example:
this:
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
into this:
{0, 1, 2, 3, 5, 6, 7, 8, 9, 4}
How about this:
int[] myArray = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
System.arraycopy(myArray, 5, myArray, 4, 5);
myArray[myArray.length-1] = 4;
In the above code, I'm using the arraycopy method to copy a range of 5 numbers starting from index 5, to index 4 in the array, and then simply set a 4 in the last position.
Notice that using arraycopy is much faster than copying the values in a loop, since it's usually implemented as a native operation which copies memory positions.
EDIT :
A more generic solution, a method for sending to the back a given position in the array:
public static void sendBack(int[] array, int idx) {
int value = array[idx];
System.arraycopy(array, idx+1, array, idx, array.length-idx-1);
array[array.length-1] = value;
}
For your example, call it like this:
sendBack(myArray, 4);
// now myArray is {0, 1, 2, 3, 5, 6, 7, 8, 9, 4}
Like this?
int start = 4;
int temp = myArray[start];
for(int i = start; i < myArray.length - 1; i++) {
myArray[i] = myArray[i+1];
}
myArray[myArray.length-1] = temp;
It's the fastest way I can guess...
Use System.arraycopy.
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.