How to iterate through a fixed tridimensional matrix efficiently (java) - java

As part of a program I'm building I need to iterate through all the points in a tridimensional matrix.
On each point I need to execute a method that takes int x, int y, int z as parameters.
The tridimensional matrix always has the same width(16) length(16) & height(256).
What is the most performant way of doing the iteration?(i'm specially concerned about CPU, not so concerned about ram usage)
Based on what i know , I think this are the most efficient methods, but I'm open to other suggestions if they are faster.
A. Iterate directly:
public void doSomethingForAllPointsInMatrix(Matrix matrix){
for(int x= 0; x<16; x++){
for(int z = 0; z<16; z++){
for(int y = 0; y<256; y++){
matrix.doSomething(x,y,z);//A method out of my control without any alternatives
}
}
}
}
B. Iterate an array containing the coordinates
private static final int[] zeroToFifteen; //Contains every number from 0 to 15
private static final int[] zeroToTwoHundredFiftyFive; //Contains every number from 0 to 255
public void doSomethingForAllPointsInMatrix(Matrix matrix){
for(int x: zeroToFifteen){
for(int z: zeroToFifteen){
for(int y: zeroToTwoHundredFiftyFive){
matrix.doSomething(x,y,z);//A method out of my control without any alternatives
}
}
}
}
Thanks in advance for any help you can provide!

A counting loop is already one of the most efficient iteration mechanisms.
Your idea to incorporate an array indicates that you are not aware that the for-each loop over an array is just syntactic sugar for a counting loop over the indices from zero to the array length.
In other words, your
public void doSomethingForAllPointsInMatrix(Matrix matrix){
for(int x: zeroToFifteen){
for(int z: zeroToFifteen){
for(int y: zeroToTwoHundredFiftyFive){
matrix.doSomething(x,y,z);//A method out of my control without any alternatives
}
}
}
}
is basically equivalent to
public void doSomethingForAllPointsInMatrix(Matrix matrix){
for(int index1 = 0; index1 < zeroToFifteen.length; index1++){
int x = zeroToFifteen[index1];
for(int index2 = 0; index2 < zeroToFifteen.length; index2++){
int z = zeroToFifteen[index2];
for(int index3 = 0; index3 < zeroToTwoHundredFiftyFive.length; index3++){
int y = zeroToTwoHundredFiftyFive[index3];
matrix.doSomething(x,y,z);//A method out of my control without any alternatives
}
}
}
}
differing from the counting loop of your first approach only by doing additional array operations, which is very unlikely to improve the performance.
Since your bounds are powers of two, you could do the entire operation with a single loop
public void doSomethingForAllPointsInMatrix(Matrix matrix) {
for(int coord = 0; coord < 0x10000; coord++) {
matrix.doSomething(coord >> 12, coord & 0xff, (coord >> 8)&0xf);
}
}
reducing the number of conditionals. However, the actual performance depends on what the JVM’s optimizer makes out of it and it might be that it can deal better with the nested loops.
So you can only try and benchmark the approaches, to find “the best”, whereas “the best” may be different, depending on the system and the JVM implementation/version.
As said in the comments, the performance is likely dominated by whatever doSomething does and if the processing order is not important for your program logic, you should try with alternative iteration orders, as it may affect how the caches are utilized.

Related

What implementation is more efficient to count occurrences in a number sample?

I'm programming a Bayesian Network which will allow me to diagnose (based on the most probable diagnosis) a tumor as benign or malign. The network will learn from a large set of samples which include the results of a set of 10 medical tests, plus the diagnosis. These results will be discrete, ranging from 0 to a maximum value.
In this case, given that I will have to program a counter (int[] sample tests, int[] values), in order to count the occurrences of values[i] in the samples tests[i], which is the most efficient implementation to choose for the class "sample"?
Currently I have implemented an ArrayList<int[]>().This is how I programmed it. However, given that I'm expecting to get around 300 sets of samples (results of 10 different tests+diagnosis) I was looking for the most efficient way to implement the "Sample" class (I called it "amostra").
public class Amostra implements AmostraInt {
private ArrayList<int []> dados;
public Amostra() {
this.dados = new ArrayList<int []>();
}
public int[] count (int[] var, int []val) {
int i=0;
int[]ocorre = new int[var.length] ;
while (i< dados.size()) {
int j=0;
while (j<var.length) {
if (dados.get(i)[var[j]]==val[j])
ocorre[j]+=1;
j++;
}
i++;
}
return ocorre;
Here are some minor improvements. Changed while loop to for loop. Replaced multiple calls to dados.get(i) with one per outer loop iteration. This won't change the speed, since the JVM would optimize the call to dados.get(i) but it does make the code look more concise.
I do not know enough about the data to find a way to replace the double loop. Essentially it looks like the double loop is needed.
public int[] count(int[] var, int[] val) {
int[] ocorre = new int[var.length];
for (int i = 0; i < dados.size(); i++) {
int[] dado = dados.get(i);
for (int j = 0; j < var.length; j++) {
if (dado[var[j]] == val[j]) {
ocorre[j] += 1;
}
}
}
return ocorre;
}

Reducing the time of execution of the following code [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 5 years ago.
Improve this question
I am working on a problem. Out of 17 test cases 10 works fine and gives the result in less than a second but in 7 cases it is taking 2 seconds which are beyond the time limit. Following is the code
import java.util.*;
import java.io.*;
class TestClass
{
static PrintWriter wr = new PrintWriter(System.out);
public static void func1(int arr[], int n)
{
int temp = arr[0];
for (int jj = 0; jj < n; jj++)
{
if (jj == (n - 1))
arr[jj] = temp;
else
arr[jj] = arr[jj + 1];
}
}
public static void func2(int arr[], int n, int rt)
{
int count = 0;
for (int a = 0; a < n; a++)
{
for (int b = a; b < n; b++)
{
if (arr[a] > arr[b])
count++;
}
}
if (rt == (n - 1))
wr.print(count);
else
wr.print(count + " ");
}
public static void main(String args[]) throws Exception
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = br.readLine().trim();
StringTokenizer st = new StringTokenizer(str);
int t = Integer.parseInt(st.nextToken());
for (int i = 0; i < t; i++) //for test cases
{
str = br.readLine().trim();
st = new StringTokenizer(str);
int n = Integer.parseInt(st.nextToken());
int arr[] = new int[n];
str = br.readLine().trim();
st = new StringTokenizer(str);
for (int j = 0; j < n; j++) //to take input of array for each test case
{
arr[j] = Integer.parseInt(st.nextToken());
}
for (int rt = 0; rt < n; rt++) //for number of times circular shifting of array is done
{
func1(arr, n); //circularly shifts the array by one position
func2(arr, n, rt); //prints the number of inversion counts
}
if (i != (t - 1))
wr.println();
}
wr.close();
br.close();
}
}
Can someone suggest how to optimize the code so that it takes less time in execution.
I know BufferReader and PrintWriter takes less time as compared to Scanner and System.out.print. I was using scanner and System.out.print earlier but changed it later in hope of getting less time but it didn't help. Also I did it earlier without the use of func1 and func2 and did all the operations in main only. The time in both the cases remains the same.
I am getting the currect output in all the cases so code is correct, I just need help in optimizing it.
The website you are using acquires questions from past programming competitions. I recognize this as a familiar problem
Like most optimization questions, the preferred steps are:
Do less.
Do the same in fewer instructions.
Don't use functions.
Use faster instructions.
In your case, you have an array, and you wish to rotate it a number of times, and then to process it from the rotated position.
Rotating an array is an incredibly expensive operation, because you typically need to copy every element in the array into a new location. What is worse for you is that you are doing it the simplest way, you are rotating the array one step for every step needing rotation.
So, if you have a 100 element array that needs rotated 45 steps, you would then have (3 copies per element swap) 100 * 45 * 3 copies to perform your rotation.
In the above example, a better approach would be to figure out a routine that rotates an array 45 elements at a time. There are a number of ways to do this. The easiest is to double the RAM requirements and just have two arrays
b[x] = a[(mod(x+45), a.length)]
An even faster "do less" would be to never rotate the array, but to perform the calculation in reverse. This is conceptually the function of the desired index in the rotated array to the actual index in the pre-rotated array. This avoids all copying, and the index numbers (by virtue of being heavily manipulated in the math processing unit) will already be stored in the CPU registers, which is the fastest RAM a computer has.
Note that once you have the starting index in the original array, you can then calculate the next index without going through the calculation again.
I might have read this problem a bit wrong; because, it is not written to highlight the problem being solved. However, the core principles above apply, and it will be up to you to apply them to the exact specifics of your programming challenge.
An example of a faster rotate that does less
public static void func1(int arr[], int shift) {
int offset = shift % arr.length;
int [] rotated = new int[arr.length];
// (arr.length - 1) is the last index, walk up till we need to copy from the head of arr
for (int index = 0; index < (arr.length - 1) - offset; index++) {
rotated[index] = arr[index+offset];
}
// copy the end of the array back into the beginning
for ( int index = (arr.length - 1) - offset; index < arr.length; index++ ) {
rotated[index] = (offset - ((arr.length - 1) - index) - 1);
}
System.arraycopy(rotated, 0, arr, 0, arr.length);
}
This copies the array into its rotated position in one pass, instead of doing a pass per index to be rotated.
The first rule of optimisation (having decided it is necessary) is to use a profiler. This counts how many times methods are invoked, and measures the accumulated time within each method, and gives you a report.
It doesn't matter if a method is slow if you only run it a few times. If you run it hundreds of thousands of times, you need to either make it faster, or run it fewer times.
If you're using a mainstream IDE, you already have a profiler. Read its documentation and use it.
The other first rule of optimisation is, if there's already literature about the problem you're trying to solve, read it. Most of us might have invented bubble-sort independently. Fewer of us would have come up with QuickSort, but it's a better solution.
It looks as if you're counting inversions in the array. Your implementation is about as efficient as you can get, given that naive approach.
for(int i=0; i< array.length; i++) {
int n1 = array[i];
for(int j=i+1; j< array.length; j++) {
n2 = array[j];
if(n1 > n2) {
count++;
}
}
}
For an array of length l this will take ( l - 1) + ( l - 2 ) ... 1 -- that's a triangular number, and grows proportionally to the square of l.
So for l=1000 you're doing ~500,000 comparisons. Then since you're repeating the count for all 1000 rotations of the array, that would be 500,000,000 comparisons, which is definitely the sort of number where things start taking a noticeable amount of time.
Googling for inversion count reveals a more sophisticated approach, which is to perform a merge sort, counting inversions as they are encountered.
Otherwise, we need to look for opportunities for huge numbers of loop iterations. A loop inside a loop makes for big numbers. A loop inside a loop inside another loop makes for even bigger numbers.
You have:
for (int i = 0; i < t; i++) {
// stuff removed
for (int rt = 0; rt < n; rt++) {
// snip
func2(arr, n, rt); //prints the number of inversion counts
}
// snip
}
public static void func2(int arr[], int n, int rt) {
// snip
for (int a = 0; a < n; a++) {
for (int b = a; b < n; b++) {
// stuff
}
}
// snip
}
That's four levels of looping. Look at the input values for your slow tests, and work out what n * n * n * t is -- that an indicator of how many times it'll do the work in the inner block.
We don't know what your algorithm is supposed to achieve. But think about whether you're doing the same thing twice in any of these loops.
It looks as if func1() is supposed to rotate an array. Have a look at System.arrayCopy() for moving whole chunks of array at a time. Most CPUs will do this in a single operation.

Array Multiplication

new programmer here and I am a little confused on this code sample I'm working on. Basically I'm taking arrayA and passing it down to my method, I would then like my method to take and multiply each adjacent numbers, therefore my total should come out to 962, return it back to main and sopln it out.
public class 8a
{
public static void main(String [] args)
{
int [] arrayA = {10,5,100,3,6,2,30,20};
int result = sumOfProducts(arrayA);
}
public static int sumOfProducts(int [] a)
{
int counter = 1;
for(int x = 0; x < a.length; x++)
}
}
Are you sure 962 is the correct result? If you multiply each adjacent number and sum up the results, your return value should be 1540. You seem to take only every other pair into consideration:
10*5 ok
5*100 not
100*3 ok
3*5 not
...etc.
If you want to sum up of the results of every adjacent pair multiplication (also the ones marked with 'not'), you can simply go through the array like this:
int sum= 0;
for(int x = 0; x < arrayA.length-1; x++)
sum+=(arrayA[x]*arrayA[x+1]);
On the other hand, if you are REALLY 100% sure you want to leave out every other pair and get to the 962 result:
int sum= 0;
for(int x = 0; x < arrayA.length-1; x+=2)
sum+=(arrayA[x]*arrayA[x+1]);
However, this only works for arrays with an even number of entries. And since this is part of an exercise, i would consider the first solution to be far more likely to be the indended one.

loops in a two-dimensional array

import java.util.Random;
public class arrayClass
{
public static void main(String [] args)
{
int [][] array = new int [5][5];
Random gen = new Random();
for(int x = 0; x < array.length; x++)
{
array[x][2]= gen.nextInt(15) + 1;
}
}
}
I know the code is brief but it might be enough for you to understand
Okay so my goal right now is to put random numbers into each cell without "brute forcing" it(so using loops). I was wondering if there is a way to manipulate two variables in a for loop. Also, how could I make it so that the first row will increase one cell when the cells within the row is done in a loop (in this case cell 0 through 4 in one row)
And is there a way to output a specific range of cells?
thanks and sorry I know this might be pretty confusing
I think you really should use a double for loop here:
for (int x=0; x < array.length; x++) {
for (int y=0; y < array[x].length; ++y) {
array[x][y]= gen.nextInt(15) + 1;
}
}
You could use a single for loop to populate the 2D array, but it would require an external loop counter, and in the end would be functionally similar to a double loop.

Dynamic nested loops with dynamic bounds

I have a LinkedList< Point > points ,with random values:
10,20
15,30
13,43
.
.
I want to perform this kind of loop:
for (int i= points.get(0).x; i< points.get(0).y; i++){
for (int j= points.get(1).x; j< points.get(1).y; j++){
for (int k= points.get(2).x; k< points.get(2).y; k++){
...
...
}
}
}
How can I do that if I don't know the size of the list?
There's probably a better way to solve equations like that with less cpu and memory consumption but a brute-force approach like your's could be implemented via recursion or some helper structure to keep track of the state.
With recursion you could do it like this:
void permutate( List<Point> points, int pointIndex, int[] values ) {
Point p = points.get(pointIndex);
for( int x = p.x; x < p.y; x++ ) {
values[pointIndex] = x;
//this assumes pointIndex to be between 0 and points.size() - 1
if( pointIndex < points.size() - 1 ) {
permutate( points, pointIndex + 1; values );
}
else { //pointIndex is assumed to be equal to points.size() - 1 here
//you have collected all intermediate values so solve the equation
//this is simplified since you'd probably want to collect all values where the result is correct
//as well as pass the equation somehow
int result = solveEquation( values );
}
}
}
//initial call
List<Point> points = ...;
int[] values = new int[points.size()];
permutate( points, 0, values );
This would first iterate over the points list using recursive calls and advancing the point index by one until you reach the end of the list. Each recursive call would iterate over the point values and add the current one to an array at the respective position. This array is then used to calculate the equation result.
Note that this might result in a stack overflow for huge equations (the meaning of "huge" depends on the environment but is normally at several 1000 points). Performance might be really low if you check all permutations in any non-trivial case.

Categories

Resources