created 05/31/03; edits 11/09/2012, 02/14/2015

# Chapter 67 Programming Exercises

The algorithms in Chapter 61, "Useful Array Algorithms", can be extended to work with two-dimensional arrays. The first several exercises ask you to do this.

## Exercise 1 — Sum of All Array Elements

Complete the following program so that it computes the sum of all the elements of the array. Write the program so that it works even if the dimensions of the rows and columns are changed. In other words, use `length` rather than hard-coded numbers.)

```import java.io.* ;

public class ArraySum
{

public static void main ( String[] args )
{
int[][] data = { {3, 2, 5},
{1, 4, 4, 8, 13},
{9, 1, 0, 2},
{0, 2, 6, 3, -1, -8} };

// declare the sum
???

// compute the sum
for ( int row=0; row < data.length; row++)
{
for ( int col=0; col < ???; col++)
{
???
}
}

// write out the sum
System.out.println(  );

}
}
```

## Exercise 2 — Sum of Each Row

Complete the following program so that it computes the sum of the elements in each row.

```import java.io.* ;

public class RowSums
{

public static void main ( String[] args )
{
int[][] data = { {3, 2, 5},
{1, 4, 4, 8, 13},
{9, 1, 0, 2},
{0, 2, 6, 3, -1, -8} };

// declare the sum
???

// compute the sums for each row
for ( int row=0; row < data.length; row++)
{
// initialize the sum
???

// compute the sum for this row
for ( int col=0; col < ???; col++)
{
???
}

// write the sum for this row
System.out.println(  );
}

}
}
```

## Exercise 3 — Sum of Each Column (Very Tricky)

Write a program so that computes and prints the sum of each column of the array.

This problem is much harder than the previous because some rows have more columns than others. You can't just reverse the inner and outer loops of the previous program because this will try to access columns that don't exist in some rows. One solution is to create a second 1D array that holds the column sums. Make a first pass over the data array to determine how long this array of sums should be. Iterate over the array as before adding each array element to the appropriate sum as it is encountered.

It is possible to solve this problem without using a second array, but the logic is tricky. You will still need a first pass over the array.

## Exercise 4 ― Maximum and Minimum Elements

Complete the following program so that it computes the maximum and minimum of the elements in the array. Write the program so that it works even if the dimensions of the rows and columns are changed. Use `length` rather than hard-coded numbers.)

It is surprisingly easy to get this wrong. Think carefully about how `max` and `min` should be initialized. Debug your program by editing the array. Change it in unexpected ways, such as all negative values, or the largest element as the last, or first, or all elements the same.

```import java.io.* ;

public class ArrayMaxMin
{

public static void main ( String[] args )
{
int[][] data = { {3, 2, 5},
{1, 4, 4, 8, 13},
{9, 1, 0, 2},
{0, 2, 6, 3, -1, -8} };

// declare and initialize the max and the min
???

//
for ( int row=0; row < data.length; row++)
{
for ( int col=0; col < ???; col++)
{
???
}
}

// write out the results
System.out.println( "max = " + max + "; min = " + min );

}
}
```

## Exercise 5 ― Largest Elements

Modify the program so that it computes and prints the largest element in each row.

## Exercise 6 — Reversal of Elements in Each Row

Write a program that reverses the order of the elements in each row of the matrix. Print out the resulting matrix.

```import java.io.* ;

public class ReverseRow
{
static int[][] data = { {3, 2, 5},
{1, 4, 4, 8, 13},
{9, 1, 0, 2},
{0, 2, 6, 3, -1, 8},
{-1, -2, -3, 4, 5, 45  },
{56},
{0, 1, 2, 3, 4, 5, 6, 7} };

private static void printArray()
{
for ( int row=0; row < data.length; row++)
{
for ( int col=0; col < data[row].length-1; col++)
System.out.print( data[row][col] + ", " );
System.out.println( data[row][data[row].length-1] );
}
}

public static void main ( String[] args )
{
// print out the initial array
printArray();
System.out.println();

// reverse each row
for ( int row=0; row < data.length; row++)
{
int endInx = data[row].length;
for ( int col=0; col < ??? ; col++)
{
????
}
}

// print out the reversed array
printArray();
}
}
```

## Exercise 7 — Image Smoother (long)

A gray-level image is sometimes stored as a list of `int` values. The values represent the intensity of light at discrete positions in the image.

An image may be smoothed by replacing each element with the average of the element's neighboring elements.

Say that the original values are in the 2D array "image". Compute the smoothed array by doing this: Each value `smooth[r][c]` is the average of nine values:

```
image[r-1][c-1], image[r-1][c  ], image[r-1][c+1],
image[r  ][c-1], image[r  ][c  ], image[r  ][c+1],
image[r+1][c-1], image[r+1][c  ], image[r+1][c+1].
```

Assume that the image is rectangular, that is, all rows have the same number of columns. Use integer arithmetic for this so that the values in `smooth` are integers.

```import java.io.* ;

public class Smooth
{

public static void main ( String[] args )
{
int[][] image  = {{0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,5,5,5,5,5,5,5,5,0,0},
{0,0,5,5,5,5,5,5,5,5,0,0},
{0,0,5,5,5,5,5,5,5,5,0,0},
{0,0,5,5,5,5,5,5,5,5,0,0},
{0,0,5,5,5,5,5,5,5,5,0,0},
{0,0,5,5,5,5,5,5,5,5,0,0},
{0,0,5,5,5,5,5,5,5,5,0,0},
{0,0,5,5,5,5,5,5,5,5,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0}};

// assume a rectangular image
int[][] smooth = new int[ image.length ][ image[0].length ];

// Compute the smoothed value for
// non-edge locations in the image.

for ( int row=1; row<image.length-1; row++ )
{
for ( int col=1; col<image[row].length-1; col++ )
{
???
smooth[row][col] = sum/9;
}
}

// write out the input

// write out the result

}
}
```

The edges of the image are a problem because only some of the nine values that go into the average exist. There are various ways to deal with this problem:

1. Easy (shown above): Leave all the edge locations in the smoothed image to zero. Only inside locations get an averaged value from the image.
2. Harder: Copy values at edge locations directly to the smoothed image without change.
3. Hard: For each location in the image, average together only those of the nine values that exist. So at the edges of the image average six values. At the corners, average four values. This calls for some fairly tricky `if` statements, or a tricky set of `for` statements inside the outer two.

Here is a sample run of the hard solution:

```C:\>java ImageSmooth

Input:
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 5 5 5 5 5 5 5 5 0 0
0 0 5 5 5 5 5 5 5 5 0 0
0 0 5 5 5 5 5 5 5 5 0 0
0 0 5 5 5 5 5 5 5 5 0 0
0 0 5 5 5 5 5 5 5 5 0 0
0 0 5 5 5 5 5 5 5 5 0 0
0 0 5 5 5 5 5 5 5 5 0 0
0 0 5 5 5 5 5 5 5 5 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0

Output:
0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 1 1 1 1 0 0
0 1 2 3 3 3 3 3 3 2 1 0
0 1 3 5 5 5 5 5 5 3 1 0
0 1 3 5 5 5 5 5 5 3 1 0
0 1 3 5 5 5 5 5 5 3 1 0
0 1 3 5 5 5 5 5 5 3 1 0
0 1 3 5 5 5 5 5 5 3 1 0
0 1 3 5 5 5 5 5 5 3 1 0
0 1 2 3 3 3 3 3 3 2 1 0
0 0 1 1 1 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0
C:\>
```

Once you have the program working with hard-coded data, modify it so that it reads its data using input redirection. Use your programming editor to create some interesting input files, or create input files by doing the next exercise.

Further modify the program so that it writes out only the smoothed image, as text, one integer per line. This output can be redirected to a text file and then used as input for the image display program (see the second following exercise.)

## Exercise 8 — Image Creator (short)

This program uses no arrays. It is put here because it is useful for use with some of the other programs of this section.

Write a program that creates a 64 by 64 image as a text file. The image will consist of eight bands of increasingly higher values. Think of the image as 64 rows of 64 integers, but actually write out one integer per line. This is for the convenience of the programs the input the image.

The image starts out with 8 rows of zero, so the program writes 8 times 64 zeros (as character '0'). Next, the image has 8 rows of eight, so the program writes 8 times 64 eights (as character '8'). Next, the image has 8 rows of sixteen, and so on. Write one value per line, without spaces or commas.

Use output redirection to send the output to a file. Use this file as input for you image smoother (previous exercise), or for the image display program (next exercise).

This is a very short program. The body consists of three lines: a double `for` loop with a one line loop body.

## Exercise 9 — Image Display (medium length)

It would be nice to display your images by some means other than printing out integers. Ideally, your programs should read and write images using standard image formats. But actual image formats, like gif, tiff, and jpeg are very complicated. Instead, write a program that displays an image by using characters to represent brightness levels.

Write a program that reads in a file that contains one integer per line. Each integer represents one location in the image. Assume that there are 64 rows and 64 columns in the image. Assume that the integers are in the range 0 to 63.

For each integer, write out a single character depending on its value:

• 0 to 7: space
• 8 to 15: .
• 16 to 23: ,
• 24 to 31: -
• 32 to 39: +
• 40 to 47: o
• 48 to 55: O
• above 55: X

Don't put extra spaces between characters. Start a new line after each row of 64 characters. This is one place where the `switch` statement is convenient. To use it, divide the input value by 8 to get the integer for the `switch`. Or you can use eight `if-else` statements if you prefer.