3
\$\begingroup\$

I have been asked to write Java method code to do the below:

+---+---+---+---+---+
| 0 | 0 | 0 | 0 | 0 |
+---+---+---+---+---+
| 0 |   |   |   | 0 |
+---+---+---+---+---+
| 0 |   |   |   | 0 |
+---+---+---+---+---+
| 0 |   |   |   | 0 |
+---+---+---+---+---+
| 0 | 0 | 0 | 0 | 0 |
+---+---+---+---+---+

I am assuming that they are NOT asking me to create a char[5][5]; i.e :

char[][] grid = {
    {'0','0','0','0','0'},
    {'0',' ',' ',' ','0'},
    {'0',' ',' ',' ','0'},
    {'0',' ',' ',' ','0'},
    {'0','0','0','0','0'}
};

I am assuming that the method will take a 2D array of int i.e int[][] and just reset the fence values to zero, and not changing the inner values. And that the array sizes is not fixed.

Having assumed that, I came up with below answer:

// Original answer
public int[][] initGrid1(int[][] grid) {
    int initVal = 0;
    int maxRows = grid.length;
    int maxCols = grid[0].length;

    for (int rows = 0; rows < grid.length; rows++) {
        for (int cols = 0; cols < grid[0].length; cols++) {
            if (rows == 0 || rows == maxRows - 1) {
                grid[rows][cols] = initVal;
            }
            if (cols == 0 || cols == maxCols - 1) {
                grid[rows][cols] = initVal;
            }
        }
    }
    return grid;
}

The response I got was: Isn't there a simpler way to do this?

Below are some of options I later came up with. I would like to know if you know of simpler way to do. Hoping to do this with Java8 features but found it difficult as individual occurrence needed to be identified for location.

// Option 2
public int[][] initGrid2(int[][] grid) {
    int initVal = 0;
    int maxRow = grid.length - 1;
    int maxCol = grid[0].length - 1;

    for (int rows = 0; rows < grid.length; rows++) {
        grid[rows][0] = initVal;
        grid[rows][maxCol] = initVal;
        for (int cols = 0; cols < grid[0].length; cols++) {
            grid[0][cols] = initVal;
            grid[maxRow][cols] = initVal;
        }
    }
    return grid;
}

If the grid is assumed to be a square.

// Option 3
public int[][] initGrid3(int[][] grid) {
    int initVal = 0;
    int maxlen = grid.length - 1;
    for (int j = 0; j < grid.length; j++) {
        grid[j][0] = initVal;
        grid[j][maxlen] = initVal;
        grid[0][j] = initVal;
        grid[maxlen][j] = initVal;
    }
    return grid;
}

If I traverse through the array with a cursor (c):

// Option 4
public int[][] initGrid4(int[][] grid) {
    int initVal = 0;
    int xL = grid.length;
    int yL = grid[0].length;
    int max = xL * yL;
    for (int c = 0; c < max; i++) {
        int x = c / xL;
        int y = (c == 0) ? 0 : c % yL;
        if (x == 0 || x == (xL - 1)) {
            grid[x][y] = initVal;
        }
        if (y == 0 || y == (yL - 1)) {
            grid[x][y] = initVal;
        }
    }
    return grid;
}

Using Java 8 feature, I was stuck with below, I don't if there is an option here:

grid[0] = IntStream.range(0, grid.length).map(i -> 0).toArray();
...don't know what to do in between.
grid[maxlen-1] = IntStream.range(0, grid.length).map(i -> 0).toArray();

1) So the big question; what is simpler?: (readability and maintainability) or smaller code or using latest features? Of course your assistance should not be just words but also code snippet.

2) And do you agree with my first answer?

\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

Could it be that you make too many assumptions? Probably you should really create a new array and not "write the fence" in an existing one.

I guess this would simplify the code by just creating an all zero arrays for the first and last element of the outer array and an array with only the zero at start and the end for all other rows.

Given your assumptions are correct. Using a function to fill the array would simplify your solution significant. In Java this is done with Array.fill.

private static int[][] initGrid(final int[][] grid) {
    assert grid.length >= 2;
    final int fence = 0;
    Arrays.fill(grid[0], fence);
    for(int[] row : grid) { 
       row[0] = row[row.length -1] = fence; 
    }
    Arrays.fill(grid[grid.length - 1], fence);
    return grids;
}
\$\endgroup\$
2
  • \$\begingroup\$ You could do a for(int[] a : grids) { a[0] = a[a.length -1] = fence; } and then fill the first and last, right? \$\endgroup\$
    – JollyJoker
    Commented Nov 18, 2016 at 14:37
  • \$\begingroup\$ @JollyJoker that's true. it would make the code even more understandable and overwriting some items twice is no problem. will change my answer. \$\endgroup\$
    – leo
    Commented Nov 18, 2016 at 15:07
1
\$\begingroup\$

Regarding 1) Readability should be the mainfocus.

Your solution (3) looks the best in my opinion and could be extended to support non-square arrays by dividing the for-loop into two separate loops, one for the rows, one for the columns. All of your other solutions are looping over the whole array, whereas you only have to iterate over the 4 sides.

Below your solution (3) splitted into two loops (using streams as loop-replacement):

public static void init(
        final int[][] grid) {
    ////
    final int val = 0;
    final int maxRow = grid.length - 1;
    final int maxCol = grid[0].length - 1;

    if (IntStream.rangeClosed(1, maxRow).anyMatch((row) -> grid[row].length - 1 != maxCol))
        throw new IllegalArgumentException("Invalid array");

    IntStream.rangeClosed(0, maxCol).forEach((col) -> grid[0][col] = grid[maxRow][col] = val);
    IntStream.rangeClosed(0, maxRow).forEach((row) -> grid[row][0] = grid[row][maxCol] = val);
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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