CS 314 Specification 3 - Using Multiple Classes - Baby Names
Programming Assignment 3: Individual Assignment. You must complete this assignment on your own. You may not acquire from any source (e.g. another student, an internet site, generative AI / chatbot / LLM such as chatGPT) a partial or complete solution to a problem or project that has been assigned. You may not show another student your solution to the assignment. You may not have another person (current student, former student, tutor, friend, anyone) “walk you through” how to solve an assignment. You may get help from the instructional staff. You may discuss general ideas and approaches with other students but you may not develop or debug code together. Review the class policy on collaboration from the syllabus.
The purposes of this assignment are
CAUTION: Take care to ensure your IDE does not add any non standard Java imports for other Java classes called Name or Names. In the past students submitted code with bad imports and lost all correctness points due to compile errors. Compile your .java files on the lab machines from the command line if you want to be sure you do not have any non standard Java imports.
Files:
File | Responsibility | |
Source Code | NameSurfer.java | Provided by me and you |
Source Code | NameRecord.java | Provided by you. |
Source Code | Names.java | Provided by me and you. |
data files |
names.txt
(The primary data file.)
names2.txt (Another data file with a different starting decade and a
different number of ranks per name.)
names4.txt (With the
ranks from the decade of 2010 added!) |
Provided by me. |
sample run log | nameSurferLog.txt Your output should roughly match this example. We won't be grading on the output of NameSurfer. | Provided by me. |
Submission | NameSurfer.java, NameRecord.java, and Names.java to Assignment 3 on Gradescope. | Provided by you |
Description: This assignment is based on an assignment created by Nick Parlante and Stuart Reges' version of that assignment..
For this assignment you may not share your tests, but you CAN share your results when using different data files such as names2.txt and / or names4.txt
Complete a program that allows a user to query a data base of the 1000 most popular baby names in the United States per decade for a given number of decades under the constraints of the General Assignment Requirements and as described below.
As always, you may add helper methods and should do so to provide structure to the program and reduce redundancy.
One additional constraint:
You must use the ArrayList
class in your solution as discussed
below.
Your program processes a file with data obtained from the Social Security
Administration. SSA has a web site showing the
distribution of names chosen for children over the last 100 years in the
Nick Parlante got the idea for this assignment from an article by Peggy Orenstein of the New York Times, Where have all the Lisas Gone?
Recently there was an article on predicting a someone's age based on their name.
And some names that surge in popularity in a given decade turn out to be very old names. For instance, Tiffany. (Link to a CGP Grey video on YouTube that covers the history of the name Tiffany.)
The first example data file you are given
is based on the 1000 most popular
male and female names for kids born in the
The first two lines of the file are the base decade and the number of decades. The base decade indicates the decade for the first rank. The second line is an integer than indicates the number of decades each name is ranked. This value shall be greater than or equal to 2. The given file starts
1900
11
The rest of the data file are names and there ranks. There is
no indication in the data I give you whether a name is a female or male name. On each line
there is a name,
followed by the rank of that name in the decades 1900, 1910, 1920,
..., 2000 (11 numbers), for the example file. Your program must
handle different starting decades and number of ranks correctly.
Of course the starting decade and number of decades can vary. Look at the other example data files, names2.txt and names4.txt.
If a line does not have the correct number of ranks based on the the integer at the top of the file, your program shall ignore that line. (In other words do NOT include a NameRecord for this data in the Names object for lines in the data file without the correct number of ranks.)
Likewise, if a name has all zeros for ranks then do NOT include a NameRecords object for that line in the Names object.
You may assume a given String never appears more than once as a name in a file. You may assume each line starts with a token representing a name and any tokens that follow this can be read as non negative ints in the range [0, 1000].
A rank of 1 indicates the name was the most popular name that year, while a rank of 997 was not very popular. A 0 in the data file means the name did not appear in the top 1000 that decade.
...
Sam 58 69 99 131 168 236 278 380 467 408 466
Samantha 0 0 0
0 0
0 272 107 26 5 7
Samara 0 0 0
0 0
0 0
0 0
0 886
Samir
0 0 0
0 0
0 0
0 920 0 798
Sammie 537 545 351 325 333 396 565 772 930 0 0
Sammy 0 887 544 299 202 262 321 395 575 639 755
Samson 0 0 0
0 0
0 0
0 0
0 915
Samuel 31 41 46 60 61 71 83 61 52 35 28
Sandi 0 0 0
0 704 864 621 695 0 0
0
Sandra 0 942 606 50 6 12 11 39 94 168 257
...
Note, a 0 in the data file means the name was NOT RANKED in the top 1000 during the corresponding decade. It has some unknown rank greater than 1000. When you store a 0 from the data file in your NameRecord objects you may use something other than 0 if you think it will make your algorithms easier to implement. This is a suggestion, not a requirement. There are some trade offs involved. (Recall altering the way data is stored to fit our needs is part of the power of encapsulation.)
Also note the data does not indicate if a name was a girl's name or a boy's name. If a name appeared on the list of boys and girls names for a given decade the rank closest to one was used.
We see that “Sam” was #58 in 1900 and is slowly moving down. “Samantha” popped on the scene in 1960 and is moving up strong to #7. “Samir” barely appears in 1980, but by 2000 is up to #798.
You are given one one partial class, NameSurfer.java
. This
is the main driver class. After creating the
database of names encapsulated in a class called Names.java
the
program displays a menu and allows the user to make various queries of the
database.
Important. Do not hard code or assume every file will start with 1900 and / or have 11 ranks per name. Your program must read those values from the file and work correctly. I recommend you create your own results with names2.txt and names4.txt, then post the results to Ed discussion to compare with your classmates.
Suggested steps for implementing the program.
0. These suggested steps describe implementing the requirements. You may add more helper methods if you want. You may store data in a different form than the input file. For example, the files uses a 0 to indicate the name had a rank greater than 1000 for a given decade. You can store a value other than 0 if you want. (The value for "not ranked in a given decade" is on the other side of the wall of abstraction.)
1. Implement and test a class called NameRecord
. Each NameRecord
object stores the data
for an individual name, including the name itself (a String
),
the base decade (decade of the first rank), and the rank of the name
for each decade. The ranks for each decade must be stored in an
ArrayList
of Integer
s. (this is to give you
practice using ArrayList.) The class must have the
following properties:
NameRecord
. NameRecord
.NameRecord.
NameRecord
, including the decades it is unranked.NameRecord
s rank for
a given decade. You can use the convention that 0 is the start decade
(1900 in the example file)), 1is the next decade (1910 in the example
file), and so forth. In other words the parameter will be between 0 to (max
number of ranks - 1) for given data set inclusive. In other words [0, num
decades) or [0, num decades - 1]. This method returns 0 if the name is
unranked in the given decade regardless of how you choose to store the
unranked status for the NameRecord class.int
for this
NameRecord's best decade. In other words it returns the decade this name
was most popular, using the most recent decade in the event of a tie. Return
the actual decade based on the initial decade for this NameRecord's ranks. Looking at the data
above, Samir's was most popular in 2000 while Sandra's best decade
was 1940 . Johns's best rank was number 1
and it occurred in 1900 and 1910. The method shall return, the most
recent decade, 1910.0 950 900 875 850 800 750 700 650
600 500 400
are always improving. The ranks 0 0 0 800 850 800
750 700 650 600 500 400
are not always improving. Recall a 0
means the name did not appear in the top 1000 names for that decade. (When
the rank is 0 indicating a name wasn't in the top 1000 in two consecutive
decades we can't really decide one way or another if it improved from one
decade to the next. So we assume it was not getting more popular.)100 150 200 202 250 300 350 400 450 460 0
are always getting
worse. The ranks 100 150 200 202 250 300 350 400 0 0 0
are not always getting worse. <NAME>
<BASE DECADE>: <RANK IN BASE DECADE>
<BASE DECADE+ 10>: <RANK IN BASE DECADE + 10>
...
<LAST DECADE>: <RANK IN LAST DECADE>
NameRecord
objects require the names be is sorted ascending order. The easiest way
to meet this requirement is to have the NameRecord
class implement the
Comparable
interface.public class NameRecord
implements Comparable<NameRecord>
compareTo
method from the
Comparable
interface. This will
be an instance method in the NameRecord
class.
public int compareTo(NameRecord other) {
NameRecord
objects
based on the String that represents the actual name. The String
class
also implement the Comparable
interface so you can simply call compare
to on the calling objects name, passing the name for the explicit
parameter to the compareTo
method, other, and return that result.NameRecord
class implements
the Comparable
interface you can then call
the static Collections.sort()
method on
lists of NameRecord
objects to sort the
list.After completing all these methods you shall thoroughly test the NameRecord class using individual lines from the names.txt file or with your own data.
Include your testing code in a method in your NameSurfer
class even though
it will not be called when the program is run. Part of the assignment grade
will be based on the tests you write for the NameRecord
class.
For this assignment you may not share tests.
2. Implement and test the Names
class. This class stores all of the
NameRecord
objects in an ArrayList
. (private
ArrayList<NameRecord>
names) This class
must have the following methods. All methods that return an ArrayList
of NameRecord
s or an ArrayList
of String
s must be in sorted
ascending order based on the names. Do not change the method headers
provided in the Names.java file.
Scanner
object. The
Scanner
object will already be hooked up to the names.txt file. The
constructor must read in the base decade and number of ranks per name and
then use the Scanner
to go through all the
names in the file and create a NameRecord
object for each
one. This can be done with the following code:
while( fileScanner.hasNextLine() ){
String line = fileScanner.nextLine();
/* create a NameRecord object based on line and add it to the
ArrayList of NameRecord objects */
}
String
into the name and the years? Use the split
method from the String
class or a Scanner
object. If you use the split
method from the String
class the statement would be:String[] parsedData = data.split("\\s+"); //data is the input String
String
into its individual components using
whitespace as delimiters. The name itself will be the first element of the
resulting array and the ranks will be in the remaining elements,
although they will be Strings
. You must convert them
to ints using the
Integer.parseInt
method.. Scanner lineScanner = new Scanner(data); //data is the input
String
Scanner
object is created you can use the next
method to pull out the name and then the nextInt
method to
pull out the ranks. See the Java documentation for more details on the
split
method from the String
class and
Scanner
objects. NameRecord
whose name is equal
to a given String
ignoring case. If there is no
NameRecord
that matches the given String
ignoring
case, return null
.ArrayList
of NameRecord
objects that contain a given substring, ignoring case. The names
must be in sorted order based on name. public ArrayList<NameRecord> getMatches(String partialName)
ArrayList
of Strings
of names that have been ranked in the top 1000 or better in every decade. The Strings must be
in sorted order based on name. public ArrayList<String> rankedEveryDecade()
ArrayList
of Strings
of names that have been ranked in the top 1000 or better in exactly one decade. The Strings must
be in sorted order based on name. public ArrayList<String> rankedOnlyOneDecade()
ArrayList
of Strings
of names that have been getting more popular every decade. The Strings
must be in sorted order based on name. public ArrayList<String> alwaysMorePopular()
ArrayList
of Strings
of names that have been getting less popular every decade. The Strings
must be in sorted order based on name. public ArrayList<String> alwaysLessPopular()
3. Complete the methods in the NameSurfer
class and add
your method the missing menu option, your interesting search or
processing.
The menu choices must be:
1 to search for names.
2 to display data for one name.
3 to display all names that appear in only one decade.
4 to display all names that appear in all decades.
5 to display all names that are more popular in every decade.
6 to display all names that are less popular in every decade.
7 to perform the method of your own design from your Names class
8 to quit
For expected program behavior review
the sample run log. Your output should match that of the sample
run log for the various operations, except that you will not trim the output
for operations that results in a large number of names and your output shall
include the description of the search you developed. Also, we will not grade
based on the output of NameSurfer, rather we will call methods from your
Names class and check those results. So there can be minor differences in
the output of your NameSurfer and what is shown in the log.
4. Neat searches. This is an interesting application because when your program is finished you can investigate various trends in naming children. In a comment at the top of the file discuss one interesting trend you found and back it up with data / results. Here are some examples. (You may not use these as your interesting trend. Do not share your interesting trend on the discussion group.)
Submission: Fill in the header for NameSurfer.java and copy it into NameRecord.java and Names.java. Replace <NAME> with your name. Note, you are stating, on your honor, that you did the assignment on your own. Submit NameSurfer.java, NameRecord.java, and Names.java to assignment 3 on Gradescope.
Checklist: Did you remember to:
NameRecord
class?NameRecord
class in the NameSurfer
class?
Do not share your tests on this assignment. You can share the results of
calls to the Names method with data files other than names.txt on Piazza.Names
class with the required methods?NameSurfer
class?NameSurfer
class?ArrayList
of Integer
s to store the ranks in the
NameRecord
class
and an ArrayList
of NameRecord
s in the Names
class to store all the NameRecord
s?NameSurfer
class?