I have two containers: a 2-dimensional NxN matrix and a 1-dimensional array which is the transposed 1D "version" of the matrix (so for a 5x5 array, I will have a 25 element array with the same values). I want to implement a query function that will take 2D coordinates as arguments but will be doing work on the equivalent 1D array.
In order to keep algorithm efficiency strictly non-quadratic I want to access only the array and not the matrix.
I've checked other questions but they all talk about converting the whole matrix to an array through nested for-loops. I don't want to do this, as that would take quadratic time to run. Instead, I want the conversion to be on-demand for a given coordinate through a query function/method. In other words for a given number of N columns/rows:
transpose(int i, int j) {
int result;
result = i * N + j;
return result;
}
This is the formula I'm using but it is not correct. For example if I want to access the element in the {5,5} position the result would be 5*5 + 5 = 30, which is greater than 25 (which would be the total number of elements for 5x5 matrix).
Thanks in advance.
If you have a 2d array and a 1d array having same elements,then the following will be true
2d[i][j]=1d[i*number_of_columns+j]
I am assuming from your post that you already have created a 1d array out of a 2d one.
Note i and j are indices and rememeber indices begin from 0
EDIT:If you are accessing an element at [5][5] (as last element)it means your array is of order 6 by 6 and not 5 by 5.So your 1d array will have 6*6=36 elements and not 25.
You can use the deepToString() method to output a 2D array to a String. This can make it easier to do things such as sort() for example.
Assuming a declared int mat2d[m][n]; with m rows and n columns, you can convert it like
int * mat1d = new int[m * n];
int k = 0;
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++i)
mat1d[k++] = mat2d[i][j];
If you just want to convert between 1D and 2D coordinates, serve yourself and make functions from this:
const int width = 10;
// from 1D coordinate to 2D coordinate
int coord_1d = 25;
int coord_x = coord_1d % width;
int coord_y = coord_1d / width;
// from 2D coordinate to 1D coordinate
coord_1d = coord_x + coord_y * width;
Your question is quite confusing, you said that you don't want nested loops, here is a just-one-loop conversion
int[][] a={
{1,2,3,4,5,6},
{4,5,6,7,8,9},
{7,8,9,1,2,3},
{1,2,3,4,5,6}
};
int[]b=new int[a.length*a[0].length];
int x=0;
for(int i=0, j=0;i<a.length&&j<a[0].length;i=(j==a[0].length-1?i+1:i),j=(j+1)%a[0].length)
b[x++]=a[i][j];
System.out.println(Arrays.toString(b));
If you want the conversion to be based on coordinates, by changing i and j values in the for loop to such coordinates will allow you to convert to array only a subset of your matrix
Related
Lets say we have a 8 x 8 2d integer array named grid and trying to select the element 0 at [5][5]
int[][] grid = new int{{1,1,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1},
{1,1,1,1,1,0,1,1},
{1,1,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1}};
Now the question is, is it possible to access the index of element 0 without using coordinates and just use a single number?
example: access the element 0 with the number 45, like a 1d array
I tried approaching this problem with a for loop but it is giving me out of range errors.
int x = 0;
int y = 0;
for (int i = 0;i<45;i++) {
x += 1;
if (x > grid[y].length) {
x = 0;
y += 1;
}
The code above is supposed to add x and y until it reaches the target element.
Eventually you would have to use the two indexes.
You could calculate the x and y given just a single number.
public static int getAt(int[][] matrix, int position) {
int columns = matrix[0].length; // column size, matrix has to be at least 1x1
return matrix[position / columns][position % columns];
}
public static void setAt(int[][] matrix, int position, int value) {
int columns = matrix[0].length; // column size, matrix has to be at least 1x1
matrix[position / columns][position % columns] = value;
}
Also in your example:
1) You don't need to use a for loop (and again eventually to access or modify the matrix you would have to use both indexes).
2) When y is greater or equal than the row size (8 in this case) you will receive an out of bounds exception because you only have 8 columns.
Finally the only way to access it with one index is if you transform the matrix to a 1d array.
Here you can see how:
how to convert 2d array into 1d?
In Java, I'd like to get the maximum element from both dimensions of a simple image array, ie:
int getWidth(Color[][] pixels){
//return max of dimension 1
}
int getHeight(Color[][] pixels){
//return max of dimension 2
}
I know how to do this for a 1D array in Java, I would just run a for loop with the condition of i < pixels.length. However, I'm not quite sure how .length works for a 2D array, or even if it does work. How would I approach this?
Will .length still work?
A 2D array is just simply an array, where the items in it are other arrays. Since .length works on a 1D array, it will surely work on all arrays - the amount of dimensions does not matter.
However, pixels.length gives you the length of the parent array - i.e. the array that contains all of the other arrays inside it. To get the length of the second dimension, you will have to get the length of the arrays inside it.
So, how do we get the length of the 2nd dimension?
We know that all of these arrays must be the same length, so we use the one at position 0 only because it is the only one that we can be 100% sure will always exist - an array should always have at least one element.
Then, we just get the length of that array - pixels[0].length.
If we consider 2D array they it is an array holding references to other arrays.
If we consider matrix like this:
{
{1,2,3},
{4,6},
{7,7,8,9}
}
So height for above matrix is 3 = no. of rows.
Width of matrix is 4 = Max(no. of element in each array).
int getHeight(Color[][] pixels) {
return pixels.length;
}
int getWidth(Color[][] pixels) {
int maxCount = 0;
int rows = pixels.length;
for (int i = 0; i < rows; i++) {
if (maxCount < pixels[i].length) {
maxCount = pixels[i].length;
}
}
return maxCount;
}
I need to flip a 1-D 64-element array of shorts (I can switch to ints if it's easier, but I assume the same processes will work for either) on it's head in Java. I represent it here as a square table for ease of understanding, since the actual problem is on a chessboard.
For example:
short[] example = new short[]
{
1, 2, 3,
4, 5, 6,
7, 8, 9
};
would become:
7 8 9
4 5 6
1 2 3
Please note that this is NOT the same as reversing the array (every answerer to similar questions I have found has made this mistake, hence my having to ask!). Reversing the array would give:
9 8 7
6 5 4
3 2 1
Apologies if I've missed any important info, any help is appreciated!
EDIT: The array is 1D and contains 64 elements, so short[64], and the reversed array is separate to the original. As far as what I've tried, I'm just struggling to wrap my head around it. I know how to reverse the array, but that's not what I'm after, and I had originally tried to reverse the index using:
byte index = (byte)(((byte)(position + 56)) - (byte)((byte)(position / 8) * 16));
Which is a code snippet I found on Chessbin, but this returns incorrect values and gives IndexOutOfBounds errors. In hindsight it's not clear to me if that code is meant to flip the index or reverse it. Since maths is not my strong suit, I tried to work around it with separate arrays.
My proposal would be like this:
public class Flipper {
public short[] flip(short[] array, int columns) {
short[] flipped = new short[array.length];
for(int i=0;i<array.length;i++){
int row = (i/columns); //use the fact that integer/integer is rounded down
int column = (i%columns);
flipped[i] = array[array.length-((columns*(row+1))-column)];
}
return flipped;
}
}
Which can be tested with:
public class FlipperTest {
private Flipper flipper = new Flipper();
#Test
public void test() {
short[] array = new short[]{1,2,3,4,5,6,7,8,9};
short[] actualResult = flipper.flip(array, 3);
assertThat(actualResult, equalTo(new short[]{7,8,9,4,5,6,1,2,3}));
}
}
Hope the code is self-explanatory
You have a physical 1D array representing a logical 2D array, and you want to swap rows. You can do this partly by mapping 2D array indices into a 1D array index.
Let height be the number of rows, and width be the number of columns.
for ( int i = 0; i < height/2; ++i ) {
int k = height - 1 - i;
for ( int j = 0; j < width; ++j ) {
short temp = array[i * width + j];
array[i * width + j] = array[k * width + j];
array[k * width + j] = temp;
}
}
I've written this for readability. You or the compiler may optimize some of the repeated computations.
You might be able to optimize further by using a 2D array, which would allow you to swap references to rows in O(height), rather than copying all the rows in O(height * width).
I'm trying to double the length of a 2D array as I add values to it. I know for a 1D an array the code for this is:
int oneD[] = new int[10];
//fill array here
oneD = Arrays.copyOf(oneD, 2 * oneD.length);
so if I have a 2D array and only want to double the amount of rows while keeping say 2 columns I figured I would just do this:
int twoD[][] = new int[10][2];
//fill array here
twoD = Arrays.copyOf(twoD, 2* twoD.length);
This however does not seem to work for the 2D array. How does one go about doubling the length of a 2D array. In this case to make it [20][2] instead.
A 2D array in Java is an array of arrays. For doubling it, you'll have to manually iterate over each row in the array and copy all of its columns in turn.
In your case something like this would do the job:
public static <T> T[][] copyOf(T[][] array, int newLength) {
// ensure that newLength >= 0
T[][] copy = new T[newLength][];
for (int i = 0; i < copy.length && i < array.length; i++) {
copy[i] = Arrays.copyOf(array[i], array[i].length);
// this should also work, just not create new array instances:
// copy[i] = array[i];
}
return copy;
}
And you could call this method, just like you called Arrays.copyOf()
Im wondering how I could split a 1d array into a 2d array in java?
I know how to set up both of them and i know that I have to iterate over both of them using for loops im just not sure how I would go about it.
I have an array of students names and i want the first 5 to go on the top line and then the next 5 on the bottom line of the 2d array so as to create groups of 5 students.
so far I have:
public void main(String[] args)
{
for (int x=0; x<5;x++)
{
for (int y=0; y<5;y++)
{
board[x][y] = (letters)y;
System.out.print(board[x][y]);
System.out.print("");
}
}
}
How to I tell the it that i want this to be connected to the arrays
So, it sounds like your only problem is the calculation of the letters index. Try this:
for (int x = 0; x < 2; x++) {
for (int y = 0; y < 5; y++) {
board[x][y] = letters[x * 5 + y];
System.out.print(board[x][y]);
System.out.print("");
}
}
This will create 2 "rows" of 5 students each.
You can make the 2d array 5x(number of students / 5) or number of people per group by number of student / people per group /* number of groups */ so it is more dynamic.
You will only need one loop to achieve this. The loop goes through each of the names in the 1d array, get the names one by one and assign it to and appropriate index in the 2d array.
To figure out the index one of them could be just the counter of the loop mod(%) people per group this will keep the index between 0 to 4. To figure out the other index you could mod(%) the loop counter with (number of student / people per group)
so it will look like board[i%ppg][i%nog] ppg being people per group and nog being number of groups. You can easily calculate number of groups.
EDIT: 2d arrays are easy if you have a really simple way to visualize them. The trick I did when I was learning 2d arrays was to think of them as chess boards. Chess boards got vertical and horizontal indices represented by letters and number just like 2d arrays except in programming it is just numbers.
Take a closer look at this code, it's also computing the indexes even if your 1D array has a number of elements which is not divisible by 5.
String[] names = new String[104];
double size = names.length;
String[][] yetAnother = new String[(int) Math.ceil(size / 5)][5];
for (int i = 0; i < size; i++)
yetAnother[(int) Math.ceil(i / 5)][i % 5] = names[i];