Looking for an efficient way to update multi-dimensional arrays - java

I update the values of a multi-dimensional array (Y[i][t][k]). Since the update needs to be done over many iterations, the runtime of this part of the code is really important. I was wondering if anyone knows how to do this in a more efficient way.
Below is the part that needs to be updated.
double [][][] Y=new double [a.length][b.length][c.length];
for(int i=0;i<a.length;i++){
for(int j=0;j<b;j++){
for (int k=0; k<c.length; k++){
if(i==w && j==r && k==u){// w, r and u can have any value.
Y[i][j][k]=g;
}else{
Y[i][j][k]=f;
}
}
}
}
Note that:
a is int [][].
b is int.
c is int [][].
q is double.
YIN is double [][][].
F is double.
g=q*YIN[i][j][k]+(1-q)*(Y[i][j][k]-F)
f=q*YIN[i][j][k]+(1-q)*(Y[j][j][k])

You are setting every element of a region of your multidimensional array, at a cost proportional to the number of elements set, so there's no reason to think that you can do it asymptotically better. However, it is likely that you can get some speed increase by using bulk-operation methods, and by handling the special case outside the loop instead of testing for it on every iteration. For example,
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < b.length; j++) {
Arrays.fill(Y[i][j], 0, c.length, f);
}
}
if (c.length > 10) {
Y[0][0][10] = g;
}
Of course, this assumes that f is a constant expression, or at least that every evaluation of it is equal to every other (in the sense of the == operator) and produces no side effects. In that case, it is probably a bit better yet to engage bulk copying in place of bulk setting where you can do so:
for (int i = 0; i < a.length; i++) {
Arrays.fill(Y[i][0], 0, c.length, f);
for (int j = 1; j < b.length; j++) {
System.arraycopy(Y[i][0], 0, Y[i][j], 0, c.length);
}
}
if (c.length > 10) {
Y[0][0][10] = g;
}
If expression f does not satisfy the requirements above, then the best you can do might be just to lift the special case out of the loop, without changing anything else. For some expressions f and / or g, even that might not be possible, in the sense that it could produce an inequivalent result. For example, this would be the case where one or both are stateful in some relevant way, such as by closing over a counter.

As I understand from your code, your goal is to set Y[0][0][10] to g and other elements to f.
So how about forgetting about crazy loops and doing like the following code ?
Arrays.fill(Y, f);
Y[0][0][10] = g;

Related

Calculating a sum within an array index in Java

Solution: I was using sum elsewhere, and my second variation of the code doesn't update it so the issue appeared later in my code. Rather silly, and embarrassing but oh well!
This is a block of working Java code:
int sum = 0;
for (int r = 0; r < k; r++) {
sum += matrix[r][c];
}
totals[0][c] = sum;
k elements in row r are summed together in sum, which is then stored in totals at the appropriate index.
My question is, why can't I have my code like this?
for (int r = 0; r < k; r++) {
totals[0][c] += matrix[r][c];
}
Where instead of using a separate integer sum I simply calculate said sum in the correct index of totals? This produces a different and very much wrong output. Would this be a good or bad practice? For clarification totals is initialised to all 0 by this point.
I have a feeling that I'm missing something rather simple but I'm struggling to find any useful information on the topic, including what I've found on the nature of arrays in Java.
To breakdown your code:
totals[0][c] += matrix[r][c];
means,
totals[0][c] = totals[0][c] + matrix[r][c];
So now, consider from your very first iteration of for loop, you don't want to add any value previously stored in totals[0][c] right?
Now, what is the way to avoid and do the same thing in that way? just initialize to 0 before adding to it.
totals[0][c] = 0;
for (int r = 0; r < k; r++) {
totals[0][c] += matrix[r][c];
}
You need to initialize the values of totals[0][c] = 0.
To do this, you can do the following when creating the matrix:
Float[] array = new Float[c];
Arrays.fill(array, 0f);
totals.add(array);
for (int r = 0; r < k; r++) {
totals[0][c] += matrix[r][c];
}
I was using sum elsewhere in my code, which I had originally read as being a new sum and not the original. As my second variation of the code was not updating sum, the second use of it was therefore incorrect. Silly mistake on my part, but live and learn.

Flexible number of for-loops - Java

I'm looking for a way to use a flexible amount of for-loops or some solution that will do the same. Basically I want a variable to go from 0 to 100 in each loop and go through all combinations. The for-loops are nested so if I am looking for a solution for two agents I have:
for(int i = 0; i<=100; i++){
for(int j = 0; j<=100, j++){
//do some stuff with i and j
}
}
but I do not ex ante know how many agents will be needed so I'm looking for a flexible way to get the same result. This might be quite an easy question but I was not able to find a threat which gave me a working solution.
EDIT: It was pointed out to me that the question is not clear enough, I will try to demonstrate what I am trying to achieve:
Let's say I have n agents, if n == 1 then I would need this:
for(int j = 0; j<=100, j++){
//do some stuff with j
}
for n == 2 I would want:
for(int i = 0; i<=100; i++){
for(int j = 0; j<=100, j++){
//do some stuff with i and j
}
}
for n == 3 another for look around these existing ones and so on, but it need to be flexible as the user is asked for n and can type in any integer.
//EndEDIT I hope this made it clearer
Thank you in advance!
I think the easiest way to achieve this is recursively.
Assuming you want the same limits on each range (i.e. that i,j,k etc go from 0..100), you can do it like so:
void recursive(List<Integer> values, int depth) {
if (values.size() == depth) {
// Do the thing you want to do with the values, i.e. the "innermost loop".
} else {
// This is intentionally Integer, so that remove removes that value, not the element at that index.
for (Integer a = 0; a <= 100; ++a) {
values.add(a);
recursive(values, depth);
values.remove(a);
}
}
}
While there are fewer than depth values in the list, this adds each value in the range into the list in turn, and recurses.
Once there are enough values in the list, then it does the "thing" you want to do. The list will contain depth values, and you can access an individual value using values.get(i).

Is it possible to iterate through a two-dimensional array without two loops for?

For example, if I have:
int Myarray[][] = new int[][] {{1,2}, {3,4}};
for (int line=0; line < Myarray.length; line++) {
for (int column = 0; column < Myarray[0].length; column++) {
// do something ...
}
}
How could I go through the entire array without the two loops?
Well you could use just a single loop:
for (int i = 0; i < Myarray.length*Myarray.length; i++) {
int row = i / Myarray.length;
int col = i % Myarray.length;
System.out.println(Myarray[row][col]);
}
But this assumes that your 2D array is square, i.e. its width and length are the same everywhere. Another way of saying this is that the 2D array is not jagged.
Demo
Note: As #Thilo mentioned above, this won't make things run faster. If you need to touch every element in your array, then my suggested code and your current double loop basically have the same complexity.
If you don’t need to know the line or column in the “do something” code (not stated in question), you could:
Arrays.stream(Myarray).flatMap(Arrays:stream)
.forEach(n -> /* do something with “n”, the cell value */);
You can iterate without any loops:
void recursive(int[][] array, int r, int c) {
if (r >= array.length) return;
if (c >= array[r].length) {
recursive(array, r+1, 0);
} else {
System.out.println(array[r][c]);
recursive(array, r, c+1);
}
}
Then invoke with recursive(array, 0, 0) to get started.
But there is no practical benefit in doing so. This would perform poorly, because of all the extra effort involved in calling a method vs just incrementing an int. (Plus, depending upon the size of the array, you could end up with a stack overflow).

Declaring 2 variables in a for() loop

I have 2 loops like this
goodexpressions and badexpressions are string arrays
for(int i =0; i < goodexpressions.length; i++) {}
&
for(int j =0; j < badexpressions.length; j++) {}
i'm trying to declare both of these in one loop, i've got this so far but it's not correct
for(int b = 0 , c = 0; b < goodexpressions.length; b++ c < badexpressions.length; c++)
what am I supposed to do to correct this statement?
Although what you are trying to do seems like a bad idea, here is a piece of code that will work. I don't know if it does exactly what you want it to though, since that isn't completely clear to me.
for(int b = 0, c = 0; b < goodexpressions.length || c < badexpressions.length; b++, c++) { }
When doing this, though, you still have to check if b and c are inside the array index range. You can also replace the || with && in which case you won't have to do that anymore, but you will be missing some items if the arrays are not equally long.
I think this will do what you are asking:
for (int b = 0, c = 0;
b < goodexpressions.length && c < badexpressions.length;
b++, c++)
Note that there are exactly 2 semicolons separators on an old-style for loop.
And based on your comment, I think this might be better:
for (int i = 0; i < Math.min(goodexpressions.length, badexpressions.length); i++)
Notes:
It is not at all clear what the loop body is going to do. That will determine the right way to combine the loops ... or if it is just a bad idea to combine them at all.
The above code is designed to stop at the smaller of the two lengths. If you want to stop at the larger, change && to || and min to max. However, if you do that, you also need to take care to avoid array bounds exceptions.
Unless the intent is to use both goodexpression[i] and badexpression[i] at the same time (e.g. compare them, combine them, and so on), your code will be more readable and more efficient if you use two separate loops.
Another possibility might be to simply check that the two arrays have the same length.
Depending on what you want to achieve, you should do one of the following. Say you have two lists A and B...
If you want to loop over all the elements in both lists A and B, create a new list, or array, holding the elements of both lists and loop over that list.
for (int i = 0; i < combinedAandB.length; i++) {
...
}
If you want to loop over all the combinations of elements from list A and list B, you have to use nested loops.
for (int i = 0; i < A.length; i++) {
for (int k = 0; k < B.length; k++) {
...
}
}
Update: Concerning the two-variable for-loop approach in your question and the other two answers: Note that since both those variables will take on exactly the same values in each iteration of the loop, you can just as well use just one variable:
for (int i = 0; i < goodexpressions.length || i < badexpressions.length; i++) { }
But also note that this will not do you any good in terms of avoiding code duplication, since you still have to everything to both, goodexpressions[i] and badexpressions[i]. A better approach might be to write a method holding the loop and calling that method once with goodexpressions and once with badexpressions.

Local variables, "dead code" and 2D arrays problems in Java

I'm having a few problems while developing the following code in Java:
setPos(x, y);
for (int i = 0; x < size; i++) {
for (int j = 0; y < size; j++) {
if (board[x][y] == 'K')
{
System.out.println("You've found a key! CONGRATS!");
return true;
}
Eclipse notice me that i and j, as local variables, they're not used : The value of the local variable i is not used . If I change the i and write the x instead, it tells me that I'm repeating the variable.
j++ is tagged as dead code ?
Also, I have to search for a concrete type of element on the diagonal of a bidimensional array, I've been trying this with 2 for loops, as above, but no result yet.
Hope you can help me, thanks in advance!
Eclipse notice me that i and j, as local variables, they're not used
That's because you're not using them. You've assigned them values, and you've later incremented (added to) those values, but you've never used them for anything.
j++ is tagged as "dead code" (?)
For the same reason, the code increments the value of j, but j is never used, so the code does nothing. "Dead code" refers to code that has no purpose or which is never run.
Your loops don't make a lot of sense. For instance:
for (int i = 0; x < size; i++) {
Normally with a for loop, the control variable (i in this case) should appear in all three of the parts of the for statement (the initializer, the test, and the increment), like this:
for (int i = 0; i < size; i++) {
// Change here -^
But you're not doing that, you're only using i in the initializer and the increment, never in the test (x < size). The same is true of your loop with j.
Similarly, unless there's something changing the value of x, y, and/or size, then your loops will either never run (because x or y is already >= size), run once (because it happens that board[x][u] == 'K'), or they'll run forever (because x or y is < size and since nothing changes that, they just keep looping...).
Eclipse is giving you a hint where the error is:
for (int i = 0; x < size; i++) {
for (int j = 0; y < size; j++) {
you iterate over i and j, but you specify x < size and y < size as a condition. Thus you never actually use the i and j value, thus j++ and i++ is dead code.
If you really would like to use a loop, you should use the variable you use for iteration in the for-loop's condition:
for (int i = 0; i < size; i++) { // i instead of x
for (int j = 0; j < size; j++) { // j instead of y
Also, I have to search for a concrete type of element on the diagonal of a bidimensional array, I've been trying this with 2 for loops, as above, but no result yet.
Why not use a single for loop, like this:
for(int i = 0; i< size; i++)
if(board[i][i] == 'K')
{
System.out.println("You've found a key! CONGRATS!");
return true;
}
Look at this:
setPos(x, y);
if (board[x][y] == 'K') //no i or j so they are unused.
{
System.out.println("You've found a key! CONGRATS!");
return true;
}
If I change the i and write the x instead, it tells me that I'm repeating the variable.
Because x is already a variable(your function argument).so you can't declare it again.
dead code : Code that has no effect on programme.Dead code
Note:it's not a solution of your problem(because i don't know). it is just to show you the mistake.

Categories