[ Chapter Index | Main Index ]

Answers for Quiz on Chapter 7

This page contains sample answers to the quiz on Chapter 7 of Introduction to Programming Using Java. Note that generally, there are lots of correct answers to a given question.

Question 1:

What is meant by the basetype of an array?

Answer:

The base type of an array refers to the type of the items that can be stored in that array. For example, the base type of the array of type Color[] is Color.

Question 2:

What is the purpose of the following variable-arity method? What are the values of same(1,2,3), same(17,17,17,17), and same(2)? Why?

static double same( int... value ) {
    for (int i = 1; i < value.length; i++) {
        if ( value[i-1] != value[i] )
            return false;
    }
    return true;
}

Answer:

This function can be called with any number of integer parameters. It tests whether all of the parameter values are equal. The value of same(1,2,3) is false. The function begins by comparing 1 and 2; since they are not equal, it immediately returns false. The value of same(17,17,17,17) is true. The function compares value[0] with value[1], value[1] with value[2], and value[2] with value[3]. All of these values are 17, so the routine goes through the for loop without returning false, and the "return true" statement after the end of the loop is executed. For same(2), value.length is 1, and the body of the loop is never executed; the return value is true.

Question 3:

What does it mean to sort an array?

Answer:

To sort an array means to rearrange the items in the array so that they are in increasing or decreasing order (according to some criterion).

(Note: To be more accurate, we should say "non-decreasing" instead of "increasing" and "non-increasing" instead of "decreasing." An array can contain duplicate values, and in that case, its elements can't be be put into strictly increasing or strictly decreasing order.)

Question 4:

What is the main advantage of binary search over linear search? What is the main disadvantage?

Answer:

The advantage of binary search is that it is much faster. On a list of one million items, linear search would take an average of five hundred thousand steps to find an item, whereas binary search would take only 20 steps. The disadvantage is that binary search only works on a sorted list, so some extra work must be done to sort the list or to keep the list in sorted order as it is created.

Question 5:

What is meant by a dynamic array? What is the advantage of a dynamic array over a regular array?

Answer:

A dynamic array is like an array in that it is a data structure that stores a sequence of items, all of the same type, in numbered locations. It is different from an array in that there is no preset upper limit on the number of items that it can contain. This is an advantage in situations where a reasonable value for the size of the array is not known at the time it is created.

Question 6:

What does it mean to say that ArrayList is a parameterized type?

Answer:

A class name is a type, but as a parameterized type, ArrayList does not define just one type. Instead, for every object type T, there is a type ArrayList<T>. T is a "type parameter." An object of type ArrayList<T> is a list that can only hold objects of type T. We can have ArrayList<String> to represent lists of Strings, ArrayList<Integer> to represent lists of Integers, and so one. The fact that ArrayList is a parameterized type means that we don't have to create a new class for each type of list.

Question 7:

Suppose that a variable strlst has been declared as

ArrayList<String> strlst = new ArrayList<String>();

Assume that the list is not empty and that all the items in the list are non-null. Write a code segment that will find and print the string in the list that comes first in lexicographic order.

Answer:

Strings can be compared for lexicographic order using the compareTo instance method in the String class. We can find the smallest string as follows:

String smallest = strlst.get(0);
for (int i = 1; i < strlist.size(); i++) {
   String nextString = strlst.get(i);
   if ( nextString.compareTo(smallest) < 0 ) 
       smallest = nextString;
}
System.out.println("The smallest string lexicographically is " + smallest);

Alternatively, a for-each loop could be used:

String smallest = strlst.get(0);
for (String item : strlst) {
   if ( item.compareTo(smallest) < 0 ) 
       smallest = item;
}
System.out.println("The smallest string lexicographically is " + smallest)

Note that in this version, the first item in the list is compared to itself as the first step in the loop. There is no easy way to leave that item out of the for-each loop.

Question 8:

Show the exact output produced by the following code segment.

char[][] pic = new char[6][6];
for (int i = 0; i < 6; i++)
   for (int j = 0; j < 6; j++) {
      if ( i == j  ||  i == 0  ||  i == 5 )
         pic[i][j] = '*';
      else
         pic[i][j] = '.';
   }
for (int i = 0; i < 6; i++) {
   for (int j = 0; j < 6; j++)
      System.out.print(pic[i][j]);
   System.out.println();
}

Answer:

The output consists of six lines, with each line containing six characters. In the first line, i is 0, so all the characters are *'s. In the last line, i is 5, so all the characters are *'s. In each of the four lines in the middle, one of the characters is a * and the rest are periods. The output is

******
.*....
..*...
...*..
....*.
******

It might help to look at the array items that are printed on each line. Note that pic[row][col] is '*' if row is 0 or if row is 5 or if row and col are equal. The items with value '*' are shown in red.

pic[0][0] pic[0][1] pic[0][2] pic[0][3] pic[0][4] pic[0][5]
pic[1][0] pic[1][1] pic[1][2] pic[1][3] pic[1][4] pic[1][5] 
pic[2][0] pic[2][1] pic[2][2] pic[2][3] pic[2][4] pic[2][5] 
pic[3][0] pic[3][1] pic[3][2] pic[3][3] pic[3][4] pic[3][5] 
pic[4][0] pic[4][1] pic[4][2] pic[4][3] pic[4][4] pic[4][5] 
pic[5][0] pic[5][1] pic[5][2] pic[5][3] pic[5][4] pic[5][5]

Question 9:

Write a complete static method that finds the largest value in an array of ints. The method should have one parameter, which is an array of type int[]. The largest number in the array should be returned as the value of the method.

Answer:

One possible answer is:

public static int getMax(int[] list) {
   
   int max = list[0];  // This is the largest item seen so far.
   
   for (int i = 1; i < list.length; i++) {
         // Look at each item in the array.  If the item is
         // bigger than max, then set max equal to the item.
       if (list[i] > max)
          max = list[i];
   }
   
   // At this point, max is the largest item in the whole array.
   
   return max;
   
} // end getMax

(Note that this method throws an exception if the parameter list is null or if it is an array of length 0. The exception is thrown by the line "int max = list[0];". The reference to list[0] causes a NullPointerException if list is null and an ArrayIndexOutOfBoundsException if the array has length zero.)

Question 10:

Suppose that temperature measurements were made on each day of 2021 in each of 100 cities. The measurements have been stored in an array

int[][]  temps  =  new  int[100][365];

where temps[c][d] holds the measurement for city number c on the dth day of the year. Write a code segment that will print out the average temperature, over the course of the whole year, for each city. The average temperature for a city can be obtained by adding up all 365 measurements for that city and dividing the answer by 365.0.

Answer:

A pseudocode outline of the answer is

For each city {
   Add up all the temperatures for that city
   Divide the total by 365 and print the answer
}

Adding up all the temperatures for a given city itself requires a for loop, so the code segment looks like this:

for (int city = 0; city < 100; city++) {
    int total = 0;  // total of temperatures for this city
    for (int day = 0; day < 365; day++)
       total = total + temps[city][day];
    double avg = total / 365.0;  // average temp for this city
    System.out.println("Average temp for city number " 
             + city + " is " + avg);
}

Question 11:

Suppose that a class, Employee, is defined as follows:

class Employee {
   String lastName;
   String firstName;
   double hourlyWage;
   int yearsWithCompany;
}

Suppose that data about 100 employees is already stored in an array:

Employee[] employeeData = new Employee[100];

Write a code segment that will output the first name, last name, and hourly wage of each employee who has been with the company for 20 years or more. Write two versions of the code segment, one that uses a regular for loop, and one that uses a for-each loop.

Answer:

(The data for the i-th employee is stored in an object that can be referred to as employeeData[i]. The four pieces of data about that employee are members of this object and can be referred to as:

  • employeeData[i].firstName
  • employeeData[i].lastName
  • employeeData[i].hourlyWage
  • employeeData[i].yearsWithCompany

The code segment uses a for loop to consider each employee in the array.)

for (int i=0; i < 100; i++) {
    if ( employeeData[i].yearsWithCompany >= 20 )
        System.out.println(employeeData[i].firstName + " " +
                      employeeData[i].lastName + ": " +
                      employeeData[i].hourlyWage);
}

Using a for-each loop:

for ( Employee emp : employeeData ) {
    if ( emp.yearsWithCompany >= 20 )
        System.out.println(emp.firstName + " " +
                      emp.lastName + ": " +
                      emp.hourlyWage);
}

Question 12:

Convert the Employee class from the previous question into a record class. What changes would then need to be made to the previous question's solution?

Answer:

It is easy to make the conversion, remembering that the instance variables of a record class are listed in parentheses after the class name. The class body will be empty:

record Employee(
   String lastName,
   String firstName,
   double hourlyWage,
   int yearsWithCompany
) { }

(Employee objects would than have to be created using the canonical constructor, and it would not be possible to change the value of any instance variable after the object has been created. However, none of that is relevant to the solution of the previous question.)

Since the fields of a record are private, they are accessed by calling methods instead of directly. For example, emp.firstName would become emp.firstName(). The extra parentheses are the only changes that are relevant to the question. So the two loops from the previous problem would become:

for (int i=0; i < 100; i++) {
    if ( employeeData[i].yearsWithCompany >= 20 )
        System.out.println(employeeData[i].firstName() + " " +
                      employeeData[i].lastName() + ": " +
                      employeeData[i].hourlyWage() );
}

and

for ( Employee emp : employeeData ) {
    if ( emp.yearsWithCompany >= 20 )
        System.out.println(emp.firstName() + " " +
                      emp.lastName() + ": " +
                      emp.hourlyWage() );
}

(Note however that if the Employee class is a nested class in the same class that contains the for loops, then the change is not necessary, since a class has direct access to the private variables in a nested class that it contains.)

Question 13:

Write a record class to represent dates, where a Date object contains three integer fields giving the month, day, and year of the date. The canonical constructor should throw an exception if the values for the month and day are not legal. Also include a toString() method that prints a date in a form such as "5/27/2022".

Answer:

My solution assumes that months are numbered 1 through 12, and days are numbered 1 through 31. Since different months have different lengths, it's actually non-trivial to check for illegal values, especially taking into account the rule for leap years. But here is my solution:

public record Date( int month, int day, int year ) {

    public Date {  // the canonical constructor
        if ( month < 1 || month > 12 )
            throw new IllegalArgumentException("Illegal month number.");
        int maxday; // last day of the month
        switch (month) {
            case 4, 6, 9, 11 -> maxday = 30;  // April, June, September, October
            case 2 -> {  // February
                boolean isLeapYear = (year % 400 == 0)
                           || ((year % 4 == 0) && (year % 100 != 0));
                maxday = isLeapYear ? 29 : 28;
            }
            default -> maxday = 31;  // All other months
        }
        if ( day < 1 || day > maxday)
            throw new IllegalArgumentException("Illegal day number.");
    }
    
    public String toString() {
        return String.format("%d/%d/%d", month, day, year);
    }

}

Question 14:

What is the purpose of the following subroutine? What is the meaning of the value that it returns, in terms of the value of its parameter?

static double[] sums( double[][] data ) {
    double[] answers = new double[ data.length ];
    for (int i = 0; i < data.length; i++) {
        double sum = 0;
        for (int j = 0; j < data[i].length; i++)
            sum = sum + data[i][j];
        answers[i] = sum;
    }
    return answers;
}

Answer:

The purpose of this subroutine is to find the sum of the numbers in each row of the parameter array data. The answer is returned as a one-dimensional array of double. The value of answers[i] is the sum of the numbers in row number i of data.

(In the first two lines of the method, data.length is the number of rows in data. In the nested for loop, data[i].length is the number of values in the i-th row.)


[ Chapter Index | Main Index ]