13

I have a large array of arbitrary size. It's a square array. I'm trying to grasp how to traverse it diagonally like a / rather than a \ (what I already know how to do). I have the following code thus far:

char[][] array = new char[500][500];
//array full of random letters
String arrayLine = "";
for (int y = 0; y < array.length; y++) {
    for (int x = 0; x < array.length; x++) {
        for (???) {
            arrayLine = arrayLine + array[???][???];
        }
    }
    System.out.println(arrayLine);
}

I have three loops, because this is how I did the other diagonal:

for (int y = 0; y < array.length; y++) {
    for (int x = 0; x < array.length; x++) {
        for (int z = 0; z < array.length-y-x; z++) {
            arrayLine = arrayLine + array[y+z][x+z];
        }
    }
    System.out.println(arrayLine);
}

In my attempts, I keep going outside the boundaries and get an ElementOutOfBounds exception. Say the array is as below (a 3x3 instead of 500x500):

A B C
D E F
G H I

I want to print out the following as strings:

A
BD
CEG
FH
I

A previous SO question had a similar problem with integer arrays, and the solution is based off of the sum of array elements. But I'm working with chars, so I can't think of a methodology to get it.

4
  • 3
    Think about what happens when you add i and j for each point in the array. You'll notice that B, (0, 1) and D, (1, 0) both sum to 1. Consider this application when figuring this out. Note: it is also important to check bounds.
    – Obicere
    Commented Jan 25, 2014 at 3:58
  • I'm not sure I follow. A = 0,0, B + D = 1,1, C + E + G = 3,3, then 3,3, then 2,2...
    – gator
    Commented Jan 25, 2014 at 4:02
  • 2
    by i and j I referred to the coordinates. C, E and G would have a value of 2. F and H would have a value of 3. I's value is 4.
    – Obicere
    Commented Jan 25, 2014 at 4:04
  • I updated my question to reflect closer to what I'm trying to get. Your advice is sound, but I guess my oversimplification got in the way of me.
    – gator
    Commented Jan 25, 2014 at 4:12

2 Answers 2

17

Think about the coordinates of the cells:

. 0 1 2
0 A B C
1 D E F
2 G H I

For any diagonal, all of the elements have something in common: the sum of an element's coordinates is a constant. Here are the constants:

0 = 0+0 (A)
1 = 1+0 (B) = 0+1 (D)
2 = 2+0 (C) = 1+1 (E) = 0+2 (G)
3 = 2+1 (F) = 1+2 (H)
4 = 2+2 (I)

The minimum constant is the smallest coordinate sum, 0. The maximum constant is the largest coordinate sum. Since each coordinate component can go up to array.length - 1, the maximum constant is 2 * (array.length - 1).

So the thing to do is iterate over the constants. For each constant, iterate over the elements whose coordinates sum to the constant. This is probably the simplest approach:

for (int k = 0; k <= 2 * (array.length - 1); ++k) {
    for (int y = 0; y < array.length; ++y) {
        int x = k - y;
        if (x < 0 || x >= array.length) {
            // Coordinates are out of bounds; skip.
        } else {
            System.out.print(array[y][x]);
        }
    }
    System.out.println();
}

However, that will end up iterating over a lot of out-of-bounds coordinates, because it always iterates over all possible y coordinates, even though only one diagonal contains all possible y coordinates. Let's change the y loop so it only visits the y coordinates needed for the current k.

One condition for out-of-bounds coordinates is x < 0. Substitute the definition of x and solve:

x < 0
k - y < 0
k < y
y > k

So when y > k, x will be negative. Thus we only want to loop while y <= k.

The other condition for out-of-bounds coordinates is x >= array.length. Solve:

x >= array.length
k - y >= array.length
k - array.length >= y
y <= k - array.length

So when y <= k - array.length, x will be too large. Thus we want to start y at 0 or k - array.length + 1, whichever is larger.

for (int k = 0; k <= 2 * (array.length - 1); ++k) {
    int yMin = Math.max(0, k - array.length + 1);
    int yMax = Math.min(array.length - 1, k);
    for (int y = yMin; y <= yMax; ++y) {
        int x = k - y;
        System.out.print(array[y][x]);
    }
    System.out.println();
}

Note: I have only proven this code correct. I have not tested it.

4
  • How would you edit your method to make it go the opposite way? \ instead of a /
    – Singh
    Commented Oct 15, 2014 at 4:03
  • In that case, all of the elements of a diagonal have this in common: the difference in coordinates (y-x) is a constant. The remainder of the answer is much the same.
    – rob mayoff
    Commented Oct 15, 2014 at 4:26
  • Which part would i have to change to change the direction in his method? (his original question)
    – Singh
    Commented Oct 15, 2014 at 4:42
  • If you need more help, post a new question.
    – rob mayoff
    Commented Oct 15, 2014 at 5:29
1

Much simpler way is to check the sum if indexes are equals to the array.length = 1; for diagonalRight and for diagonalLeft just check if i is equals j

Example:

digonalLeft sums \ of matrix, because (0,0) (1,1) (2,2) makes the diagonal. diagonalRight sums / of matrix, because (0+2) = (1+1) = (2+0) = 2 and 2 is the array.length - 1.

long diagonalLeft = 0;
long diagonalRight = 0;

for (int i = 0; i < array.lenth - 1; i++) {
    for (int j = 0; j < array.length -1; j++) {
        if (i == j) digonalLeft += array[i][j];
        if (i + j == array.length - 1) diagonalRight += array[i][j];
    }    
}
1
  • For the loops it should be <= and not < as you're subtracting -1 from the array length.
    – Gilles
    Commented Aug 31, 2019 at 1:34

Not the answer you're looking for? Browse other questions tagged or ask your own question.