Due date: Tuesday, January 21 @ 11:59PM
This assignment will take longer than the first PA. Start as early as possible to ensure that you will be able to finish.
The purpose of this assignment is to continue building your experience with Java, recursion, command line arguments, and file I/O operations. It will consist of two parts.
The first part of the assignment will require you to draw an hourglass on the console using recursion. It has one required command-line argument, the width, which you will use to determine the size of the hourglass.
The second part of the assignment is a conversion of Hawaiian words into their phonetic pronunciation (with a slight twist in the rules). You will read in a file with Hawaiian words and write each word's pronunciation to another file.
You will also be expected to complete a README.md
answering a few questions.
There are a number of ways to get started on development. The following is the recommended way to ensure that your code will compile during grading.
ssh cs8bwi20__@ieng6.ucsd.edu
cp -r ~/../public/pa2 ~/
(this will copy the entire starter files directory to your home directory)ls ~
to verify that you have copied the pa2
directory over.git clone https://github.com/CaoAssignments/cse8b-wi20-pa2-recursion-starter.git
cd cse8b-wi20-pa2-recursion-starter
mv cse8b-wi20-pa2-recursion-starter pa2
vim Hourglass.java
or gvim Hourglass.java
javac
command.
javac file1.java file2.java etc...
javac Hourglass.java
java
command passing in the name of the class with the main method that you want to run.
java nameOfClass
java Hourglass
In this part of the assignment, you will be printing an hourglass shape to the console using recursion. The program has one required command-line argument, which determines the width of the hourglass. The width must be an integer that is odd and greater than or equal to 1. See sample output below to get a better idea of what output is expected.
The best way to ensure that your code works properly is to test it! We have provided sample inputs and their respective outputs below for you to check your output. Be sure your output matches exactly by using the string constants that we have defined and the printLine()
helper function!
Valid inputs:
java Hourglass
java Hourglass 1
java Hourglass 15
java Hourglass 109
Invalid inputs:
java Hourglass 0
java Hourglass -1
java Hourglass -25 8 1
java Hourglass 50
Sample outputs:
java Hourglass
java Hourglass 5
java Hourglass 7
java Hourglass -1
java Hourglass 0 3
Hourglass.java
You will be writing all of your code for this part of the assignment in this file. We have already defined constants that should help you complete this part. The constants that we have defined are declared as private static final
. Please use these constants so your output matches the expected result exactly. Feel free to add constants if necessary. Remember to use constants instead of having magic numbers in your code!
protected static void printLine(int width, int padding)
This helper method is given to you! This function will print a line using this format:
[p][w][p]
PADDING_CHAR
padding
times and w will have HOURGLASS_CHAR
width
times.protected static void printHourglass(int width, int padding)
This method will recursively print an hourglass to the console using the given width
. padding
is a parameter that will be useful when you are recursively calling on the function.
From a high level perspective, this method will first print the top half of the hourglass, stop when it reaches the center, and then print the bottom half of the hourglass.
To approach this function, take a look at the sample output. When we pass in 7 as our width
, what is the width of each line?
After you have identified the pattern, recall that recursion has 3 general parts to its structure: the base case, the recursive call, and the body of the function, where you perform some action at a given function call.
public static void main(String[] args)
This method will process any command line arguments and call printHourglass()
if appropriate.
You must perform command line argument validation in this order. When printing the usage or error messages, use System.out.println()
.
If no arguments were provided, print HELP_STR
and return.
Otherwise, check to make sure that only one argument was provided. If more than one argument was provided, print the appropriate error message EXTRA_ARGS_ERR
and return.
If only one argument was provided, we will parse this argument as an integer and make sure that it is a valid width. You can assume that the argument will always be a valid integer. Parse the argument using Integer.parseInt()
before performing validation checks. If the width is even or less than or equal to 0, the width is invalid, so print out INVALID_WIDTH_ERR
and return.
If the width is valid, call printHourglass()
with the appropriate arguments.
Long Hawaiian words like the fish lauwiliwilinukunuku'oi'oi may seem very intimidating to pronounce, but the language is actually suprisingly simple. Hawaiian language only has 12 of the 26 English characters: 5 vowels and 7 consonants. In this PA, you will write code that will allow a user to get the intuitive pronunciation of Hawaiian words.
Pronounce.java
At the top of the starter code, you can see some constants (private static final
variables) that are provided for you. You should use these and declare other constants to avoid the use of magic numbers.
protected boolean isVowel(char ch)
First, we write a simple helper function. This method will return true
if ch
is a vowel (a
, e
, i
, o
, or u
) and false
otherwise.
protected boolean isValidChar(char ch)
Similarly, we want a helper function to help us figure out if ch
is a valid character for the Hawaiian language. The valid characters are 'a'
,'e'
,'i'
,'o'
,'u'
,'p'
,'k'
,'h'
,'l'
,'m'
,'n'
,'w'
,' '
(the space character), '\''
(the single quotation character, since single quotes are also used to denote char
s, we need to "escape" the quote by adding the backslash to the front). In total, there are 14 valid characters (12 plus the space and the single quote).
Hint: At this point, you might realize how tedious (or maybe you're already one step ahead!) it is to write out all of these conditions. Furthermore, if you were to change the valid characters in the future, you might need to change a lot of code. Although you may learn/discover some much easier and efficient ways to do this check in the future, these are beyond the scope of the course. However, you may want to explore using a loop to iterate across the valid characters. This would work for isVowel()
too! If you choose to explore this path, you will find that the code for the two functions is nearly identical. Try using some of the provided constants.
protected boolean isValidString(String str)
We also want a helper method to check if all the characters in the given String are valid. If the input String is null
, return false
. Writing the code for this would be easy by using a loop. However, we want you to practice recursion. The use of recursion is mandatory for this method.
Note: You might find charAt()
and substring()
methods from the String
class usefulwhen manipulating the String.
Note: You should use your previously written isValidChar()
to check each character's validity.
Hint: Begin by thinking about the base case. In the base case, we want the empty string (""
to return true
). Now, for the recursive case, we can simply check a single character and recursively call isValidString()
on the remaining string (the original string minus the checked character).
public String convert(String str)
Finally, we want to convert a given Hawaiian string to its pronunciation, with only the first character being capitalized. This method should only convert "valid" strings (a string is valid if it only contains our previously-defined valid characters). If a string is not valid, then we should return the original input to this function. Notice that there is the small problem when using our isValidString()
function: the string "a"
would be valid but the string "A"
would not be, which doesn't make sense. Thus, we need to make convert()
work case insensitively.
str
is null
. If it is null
, then it is invalid and we want to return the original input. You should also add a check for the empty String here and return the original input. We won't test this empty String case but it will be useful for your own testing purposes (so that the program doesn't crash if you put the wrong input on accident).isValidString()
will only properly work on lowercase strings, so let's do that. Use the toLowerCase
method from the String
class for this. Remember that we haven't checked if the string is valid yet. If it turns out to be invalid, we want to return the original value of str
, not the lower cased one.isValidString()
method. If the string is invalid, return the original value of str
immediately.convertHelper()
method on the valid fully-lowercase string. Store the output in some variable. For now we will not write convertHelper()
but just assume that it will eventually give the correct output (the phonetic string)." hi"
or " "
), but don't do that here. Simply capitalize the zeroth character in the string without doing any checks (see expected input/output below, if the first letter is not capitalizable then nothing should be capitalized). You can do this using the substring()
method from the String
class (which you already used) combined with the Character.toUpperCase(char)
method. Return this result.Note: You only need to check if the given String is valid and change the capitalization here. The actual conversion will be handled by convertHelper()
.
Note: You can test your convert()
before implementing convertHelper()
by checking if your convert()
is able to perform the sanity check (i.e. null object and empty string input), validity check, and transform the valid string by making only the first character capitalized. Below are some sample input and output.
String input | convert(input) (before implementation of convertHelper() ) |
Explanation |
---|---|---|
null | null | |
"" | "" | |
"paul" | "Paul" | Valid string, only uppercase first letter |
"ALOHA" | "Aloha" | Valid string, only uppercase first letter |
"CHARLES" | "CHARLES" | Invalid string |
protected String convertHelper(String str)
Since this is a PA about recursion, we require you to complete this method recursively. You will not earn credit if this method is implemented iteratively (by using a loop to go through the string). We use this helper method to do the actual String conversion. After completing this method, try to think about why we have this section of code as a helper method.
To convert a given string into the pronunciation, first you want to check if the character is a vowel.
-
after the converted vowel or vowel group unless there is a space character (' '
) or single quote character ('\''
) following the vowel or vowel group (e.g. E komo mai
would be converted to Eh koh-moh meye
).The table of conversions is given below. All trailing spaces should be preserved (See example input and output).
We have given you most of the code for this method. There are 7 TODOS
, where the 3rd TODO
has 7 parts (change what the appropriate pronunciation is) and the 5th TODO
has 5 parts (change what the appropriate pronunciation is).
Hint: The recursion here should be very similar to the recursion in validString()
.
Note: You might want to untilize switch
statements here to avoid a bunch of else if
statements. You can see the Java tutorials for more details.
Vowels | Conversion |
---|---|
a | ah |
e | eh |
i | ee |
o | oh |
u | oo |
Vowel Groups | Conversion |
---|---|
ai | eye |
ae | eye |
ao | ow |
au | ow |
ei | ay |
eu | eh-oh |
iu | ew |
oi | oy |
ou | ow |
ui | ooey |
protected void convertFile(String infilename, String outfilename)
Awesome! You have now successfully converted a single Hawaiian word into its Hawaiian Phoenetic Translation. But what if we want to convert an entire file containing multiple such words?
In this method, we have two parameters:inputfilename
and outputfilename
. inputfilename
is the name of the file which has a list of Hawaiian strings (each on a separate line, each string may have multiple words though) that need to be converted into their corresponding Hawaiian phoenetic translations. The outputfilename
is the name of the file where you will have to write the converted phoenetic translations (again, each on a separate line).
We've provided you with some code that should exist in all code of this form (it has to do with handling exceptions, which we won't focus on for now). You only need to write code at spots marked with // TODO
comments. There are 2 TODO
s.
Note: Some strings have multiple words. Thus, simply convert each line (in its entirety) and write the conversion on a new line of the output file each time (each line of output file match each line of the input file). For invalid lines, rewrite the entire line to the output file. Since our convert()
method returns the original string for invalid strings, we can just write the output from convert()
for each line (thus delegating the validity checking).
protected void readUserInput()
This method is given to you! This method will help read in user input commands and process them to produce results.
There are 3 valid single letter commands a user can input:
Reading the user input should be a continuous and never ending cycle until the user explicitly wants to stop by entering the 'q' command. If the user gives any invalid input, you must print out a list of valid commands as instructions to use the program and then reprompt the user.
public static void main(String[] args)
You have reached the final step of this part! In the main method, we need to identify different "flags" (signals for a function or process) in the command line to call the corresponding functions. Just like in part 1, please check these flags in this order. There are 4 situations:
USAGE
message in the terminal no matter what other arguments are and return.-f infile outfile
. Thus, if there are only 3 arguments in the command line, then call a function that you have written to fulfill the converting functionality of this program. Otherwise, print out the USAGE
message to tell the user how to input valid arguments. After this, return.
Note: you don't need to check if the files are valid here.System.out.println()
). After printing all the conversions, return.readUserInput()
.convert()
You can now test by compiling Pronounce.java
and running Pronounce
with no extra command line arguments. This will put you in the readUserInput()
loop where you can test all the following cases (except the null case).
String input | convert(input) | Explanation (if needed) |
---|---|---|
null | null | |
"" | "" | |
"ALOHA" | "Ah-loh-hah" | Only the first letter is capitalized |
"Kokua " | "Koh-koo-ah " | Trailing space preserved |
"E komo mai" | "Eh koh-moh meye" | |
"a hui hou" | "Ah hooey how" | The first letter is capitalized |
" Hana Hou" | " hah-nah how" | Nothing is capitalized because the first character is a space |
"M3n3hun3" | "M3n3hun3" | Invalid input |
"Hau'oli Makahiki Hou" | "How'oh-lee mah-kah-hee-kee how" | |
"humuhumunukunukuapua'a" | "Hoo-moo-hoo-moo-noo-koo-noo-koo-ah-poo-ah'ah" |
README.md
Answer the following questions in a file named README.md
. Write them in sections corresponding to question letter. Remember to add a file header to your README.md
. We have provided you with sample headers in the files you have been working in.
Note You may find this site useful for question a-e and this site useful for question f.
You can create this file by using the touch command or saving the file with the .md
extension in a text editor.
touch README.md
a. What single command will print the first 13 lines (or up to 13, if fewer than 13 lines are in the file) of ./Pronounce.java
to the console?
b. What single command will list every file and directory in the current directory (including hidden files like .vimrc
)? Hidden files and directories are denoted by a .
at the beginning of their names.
c. What single command will create a file called CSE.rocks
in the current directory (without leaving the terminal by, for example, entering vim/gvim
)? (You may have already used it to create this file.)
d. How do you copy a directory named PA_Work
and all its contents with one command to the home directory? Assume PA_Work
is in the directory that you are currently in.
e. How do you rename a file named foo.f
to bar.b
with one command from the command line? Assume foo.f
is in the directory that you are currently in.
f. How do you copy all files ending with .java
in the parent directory to the current directory with one command?
Please fill out our student satisfaction survey. We are changing how we approach giving assignments and would like to hear about your experiences. After filling out the survey, please write the following sentence at the top of your README.md
file: I have completed the student satisfaction survey.
In this PA, we will focus on the following items: 1, 2, 3, 4, 5. We will start to strictly grade on style starting from PA3.
We will grade your code style thoroughly. Namely, there are a few things you must have in each file / class / method:
A full style guideline can be found here. If you need any clarifications, feel free to ask on Piazza.
Before submitting, make sure your code compiles and runs properly on ieng6 if you aren't already working on ieng6. Note: If you are on a lab computer, then your files are already on ieng6.
You can follow these steps to transfer your files to the ieng6 server.
ls cse8b-wi20-pa2-recursion
or ls your_PA2_folder_name
scp
command to transfer your files to the server.
scp -r cse8b-wi20-pa2-recursion cs8bwi20__@ieng6.ucsd.edu:~/
orscp -r your_PA2_folder_name cs8bwi20__@ieng6.ucsd.edu:~/
ssh
into the server to compile and run your code.After you have confirmed that your code works properly, if you were working remotely and need the files on your local machine, you can follow these steps. Note: If you are on a lab computer, the files are already available for you to zip and upload to Gradescope.
scp
the folder from the server to your local machine. This command assumes that your work is in your home directory on ieng6.
scp -r cs8bwi20__@ieng6.ucsd.edu:~/cse8b-wi20-pa2-recursion .
orscp -r cs8bwi20__@ieng6.ucsd.edu:~/your_PA2_folder_name .
If you want to copy a single file instead of the entire directory, you can remove the -r
flag from the respective command above and specify the path to the single file that you want to copy. For example:
scp cs8bwi20__@ieng6.ucsd.edu:~/Hourglass.java .
will copy the Hourglass.java
file located in the home directory of your ieng6 account to the current directory on your local machine.Required Submission Files
Hourglass.java
Pronounce.java
README.md
Start early and start often!