# Problem Solving with Algorithms and Data Structures using Java: The Interactive Edition

## SectionB.4Exercises

### ExercisesExercises

#### 1.

Write a program named TestAverages.java that asks the user for the name of an input file that has people’s names and test scores. Each line has the person’s name, a colon, and a list of scores separated by commas.
Next, the program asks the user for the name of an output file. The program will then read the input file and write a new output file with the names and their average scores, including the number of tests on which it is based.
Your program has to do the following error handling:
• If the input file does not exist or cannot be opened, print an appropriate error message.
• If the output file cannot be opened, print an appropriate error message.
• If an input line has a non-numeric entry for a score, print an error message to the screen with the bad data and skip that score.
• If an input line has no scores, print an appropriate message to the screen.
For this input file sampleScores.txt:
Juan Fulano: 88, 82, 89
Tran Thi B: 91, 87.5, 92, 89, 88.5
Jan Kovacs: 91, 93, 8r, 74.5
Joseph Schmegeggie:
Erika Mustermann: 79.5, 83.5, 90, 92

Here is the result of running the program several times. First, with a bad input file name:
Enter input file name with test scores: nosuchfile.txt
Cannot find input file nosuchfile.txt

With a good input file name but a bad output file name. Notice that the message tells why the output file failed:
Enter input file name with test scores: sampleScores.txt
Enter output file name for averages: /usr/output.txt
IO Error: /usr/output.txt (Permission denied)

With a good input and output file name:
Enter input file name with test scores: sampleScores.txt
Enter output file name for averages: output.txt
Ignoring bad number  8r for Jan Kovacs
No numbers found on line Joseph Schmegeggie:
File output.txt written successfully.

After the program finishes successfully, the output.txt file looks like this:
Juan Fulano: 86.33 (3 tests)
Tran Thi B: 89.60 (5 tests)
Jan Kovacs: 86.17 (3 tests)
Erika Mustermann: 86.25 (4 tests)

Here are some hints:
• Do not presume that the input file will always be named sampleScores.txt or the output file will always be named output.txt—the user gets to decide those names, not you!
• If a person has scores, but none of them are numeric, then they will have no tests to average. Your program needs to handle that situation correctly.
• Use the split method in the String class to separate the name from the scores, and use it again to separate the individual scores. You will need to convert the resulting strings to double. Do this by using the Double.parseDouble method, which throws a NumberFormatException if given a non-numeric string as its parameter.

#### 2.

In this exercise, you will consolidate data from one file to create another file in a program named Consolidate.java. The original data is in file wildfires_jan_2015.txt and was extracted from a database of 1.8 million wildfires from 1992 to 2015.
1
Short, Karen C. 2017. Spatial wildfire occurrence data for the United States, 1992-2015 [FPA_FOD_20170508]. 4th Edition. Fort Collins, CO: Forest Service Research Data Archive. doi.org
Each line in the file contains:
• the year
• the day of the year (1-365) the fire was discovered
• fire perimeter (acres)
• cause of fire (1 = lightning, 7 = arson, anything else is “other”)
The first few lines of the file look like this:
2015,1,2,2
2015,1,0,2
2015,1,1,2
2015,1,0,3
2015,1,0,3
2015,1,3,4
2015,1,0,4

Your program will read this file and create a new file where each line contains, separated by commas:
• The year
• The day of year
• The number of lightning-caused fires and their total acreage
• the number of arson-caused fires and their total acreage
• The number of fires with other causes and their total acreage
The first few lines of the output file look like this:
2015,1,0,0,2,3,57,260
2015,2,2,1,1,0,35,13
2015,3,1,0,3,1,26,123
2015,4,0,0,2,33,21,255

As in the preceding exercise, use split to separate the items, and check that data can be converted to double by catching NumberFormatException.

#### 3.

In this exercise, you will write two classes: a class that represents information about a city and a main program that processes that information. You can find some pseudocode for this exercise that may help you get the program organized and started in the repository, file CityInfo_Pseudocode.java.
First, write the City class that defines an object with these properties:
• private String country: the two-letter country code
• private String name: the city name
• private int population: the city’s population
Implement these methods:
• public City(String country, String name, int population): The constructor
• Accessors and mutators: Write an accessor (getter) and mutator (setter) for the population, and only a getter for the country code and city name; once the object is constructed, the country and city name never change. These must be public.
• public String toString(): Returns a string giving the country name, city name, and population, separated by semicolons.
Figure B.4.1 shows the UML diagram for the City class.
Then, write a class named CityInfo that contains the main() method.Use the citylist.dat file to set up the initial list of cities. The file is available from the repository. Each line of the text file has a country code, city name, and population, separated by semicolons. Your program must first read the city data file with this method:
public static ArrayList<City> readCityFile(String fileName)

This method will open the given fileName, read it, and return an ArrayList of City objects corresponding to each line of the file.
If a line in the file has bad data (non-numeric population or too many or too few entries), your program will print an error that displays the bad line without entering any new data into the ArrayList. The citylist.dat file in the repository purposely contains some lines with bad data so you can test to see if your error-handling code works. Do not write your code for this specific file; another person’s file might have bad data on different lines with different data on them.
If the file does not exist, the method prints an appropriate error message and returns an empty ArrayList<City>.
If the returned ArrayList is not empty, the program will repeatedly ask for a country code (or ENTER to quit). Once the user enters a country code, the main() method will call this method:
public static int statistics(String countryCode,
ArrayList<City> cityList)

The statistics() method will go through the city list and
• Calculate the total number of cities in the given country.
• If there are more than zero cities:
• Print the total number of cities
• Print the average population for those cities
• Otherwise, prints an appropriate error message.
• Returns the total number of cities found.
The main() method will then use this returned value. If it is greater than zero, you will write a new file name CC.dat, where CC stands for a country code. This file will have the information for the cities in that country in the same format as citylist.dat. For example, if the country code is JP, your program will create a file named JP.dat. You will use a method named
public static void writeCountryFile(String countryCode,
ArrayList<City> cityList)

to do this. If there is an IOException while opening the output file or writing the data, print an appropriate error message. You must use the exception’s getMessage() method when constructing your error message. If the file is written successfully, print a message letting the user know that the file has been created. This message must contain the file name.
Your program must handle these exceptions:
• Catch FileNotFoundExceptionwhen opening a Scanner for the input file. You could use the File.exists() method, but let’s use exceptions to get more practice.)
• Catch NumberFormatException when reading the input file and converting strings to numbers.
• You will probably need nested try/catch blocks for file input: one outside the read loop when opening the file, and one inside the read loop to skip badly formatted lines.
• Catch IOException when writing an output file.
Here are some things to note:
• You must accept input in either upper or lower case.
• You will need to loop through the cityList twice; once in statistics() to get the total and average (if applicable), and again in writeCountryFile() to create the output file. This is a design decision—we decided these are two separate tasks to be done by two methods, rather than combining both tasks into one method.
Here is what the program output might look like. Your output does not have to look exactly like this, but it must reflect the same information.
Reading city file...
"AB;Too few" does not have three entries.
"CD;Too many;1056382;extra" does not have three entries.
"EF;Bad number;one million" does not have a number on it.

Enter a two-letter country code, or press ENTER to quit: UA
Number of cities in UA: 5
Average population is 1,457,504.
File UA.dat written successfully.
Enter a two-letter country code, or press ENTER to quit: LU
No cities found in LU.
Enter a two-letter country code, or press ENTER to quit: MX
Number of cities in MX: 11
Average population is 2,427,622.
File MX.dat written successfully.
Enter a two-letter country code, or press ENTER to quit:

Here are the contents of the file UA.dat:
UA;Kiev;2797553
UA;Kharkiv;1430885
UA;Dnipropetrovsk;1032822
UA;Donets'k;1024700
UA;Odessa;1001558

Here is an example of the output you might get for an error while writing the file (I deliberately caused this error by changing my directory to be read-only).
Error writing FR.dat
FR.dat (Permission denied)