Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generalizing a for-loop in Java

I don't really know how to describe my issue, so I'll just show a code example:

int[][][] mat;
int n;
int specificValue;

for (int i = 0; i < n; i++) {
    if(mat[i][n-i][3] != specificValue) {
        doStuff();
    }
}

I'm looking up Integer values in a 3d-array. For each field I have to use one of these:

  • a counter running from zero to n
  • a counter running from n to zero
  • a fixed value

So i've tried to build a Method that would save me from writing this for loop about 20 times, but i failed, so that's where i need help. My idea was something like this:

search(Loop.UP, Loop.DOWN, Loop.FIXED);

where "Loop" would be an enum representing one of my possibilities, but I don't know how to implement it or if this is even possible in Java without hardcoding every possible combination.

Hope you can help :)


OK, more specific... with my setup i'm drawing a vector through this 3d-array, a diagonal to be specific and i want to know what values are on this vector and only on this vector.

And because there is more than one possibility to draw such a vector, i'd like to have a more general method to get to the values. My search could just be as simple as

search(Loop.UP, Loop.FIXED, Loop.FIXED);   // one plane

which would be a simple for-loop with one counter, but also

search(Loop.DOWN, Loop.UP, Loop.UP);   // through all three planes
like image 791
klamann Avatar asked Sep 02 '11 01:09

klamann


3 Answers

Path pathX = new Path.Up();
Path pathY = new Path.Down(n);
Path pathZ = new Path.Fixed(3);

for (int i = 0; i < n; i++) {
    if(mat[pathX.pos(i)][pathY.pos(i)][pathZ.pos(i)] != specificValue) {
        doStuff();  
    }
}

where

public interface Path {
    public int pos(int i);

    public static class Up implements Path {
         @Override public int pos(int i) { return i; }
    }

    public static class Down implements Path {
         private int n;
         public Down(int n) { this.n = n; }
         @Override public int pos(int i) { return n - i - 1; }
    }

    public static class Fixed implements Path {
         private int v;
         public Down(int v) { this.v = v; }
         @Override public int pos(int i) { return v; }
    }

I didn't use an Enum because Down depends on n and Fixed on some value.

like image 178
toto2 Avatar answered Oct 02 '22 03:10

toto2


You could use a list of indices. In Python, it could look something like this:

LOOP_UP = 20
LOOP_DOWN = LOOP_UP + 20
LOOP_FIXED = LOOP_DOWN + 20

def indexesOfLoopType(loopType, val):
    if loopType == LOOP_UP:
        return range(val)    
    if loopType == LOOP_DOWN:
        return range(val, 0)
    return [val] * val # make a list [val, val, val... ] of length val

def search(loopFirstIndex, loopSecondIndex, loopThirdIndex):
    # use indexesOfLoopType() to get lists of indexes
    # use those lists to iterate over mat
like image 29
Nick Heiner Avatar answered Oct 02 '22 02:10

Nick Heiner


The best I can think of at the moment is this:

static final int UP = -2, DOWN = -1;

static void loop1(int[][][] A, int t1, int t2, int t3) {
    switch (t1) {
    case UP:
        for (int i = 0; i < A.length; i++)
            loop2(A[i], t2, t3);
        break;
    case DOWN:
        for (int i = A.length - 1; i >= 0; i--)
            loop2(A[i], t2, t3);
        break;
    default:
        loop2(A[t1], t2, t3);
    }
}

static void loop2(int[][] A, int t2, int t3) {
    switch (t2) {
    case UP:
        for (int i = 0; i < A.length; i++)
            loop3(A[i], t3);
        break;
    case DOWN:
        for (int i = A.length - 1; i >= 0; i--)
            loop3(A[i], t3);
        break;
    default:
        loop3(A[t2], t3);
    }
}

static void loop3(int[] A, int t3) {
    switch (t3) {
    case UP:
        for (int i = 0; i < A.length; i++) {
            // Do something with A[i] here, such as...
            System.out.println(A[i]);
        }
        break;
    case DOWN:
        for (int i = A.length - 1; i >= 0; i--) {
            // Do something with A[i] here, such as...
            System.out.println(A[i]);
        }
        break;
    default:
        // Do something with A[t3], such as...
        System.out.println(A[t3]);
    }
}

FIXED is the only option which requires an index, and is thus encoded as an index. UP and DOWN are not indices, so they are encoded using negative numbers. Usage would go something like

public static void main(String[] args) {
    int[][][] m = { { { 1, 2 }, { 3, 4 } }, { { 5, 6 }, { 7, 8 } } };
    loop1(m, DOWN, 1, UP);
}

With my System.out.println example, the output would be

7
8
3
4
like image 44
Timbits Avatar answered Oct 02 '22 04:10

Timbits