Question
Please do part 2 and last part of part 1 Imagine taking a book (say, Pride and Prejudice ) and determining the probability with which
Please do part 2 and last part of part 1
Imagine taking a book (say, Pride and Prejudice) and determining the probability with which each character occurs. (By character I mean char in the Java sense, not Elizabeth Bennet or Mr. Darcy!) You'd probably find that spaces are the most common, that 'e' is fairly common, and that 'q' is rather uncommon. After completing this level 0 analysis, you'd be able to produce random Pride and Prejudice text based on character probabilities. It wouldn't have much in common with the real thing, but at least the characters would tend to occur in the proper proportion.
Now imagine doing a slightly more sophisticated level 1 analysis by determining the probability with which each character follows every other character. You would probably discover that 'h' follows 't' more frequently than 'x' does, and you would probably discover that a space follows '.' more frequently that ',' does. You could now produce some randomly generated Pride and Prejudice by picking a character to begin with and then always choosing the next character based on the previous one and the probabilities revealed by the analysis.
Now imagine doing a level k analysis by determining the probability with which each character follows every possible sequence of characters of length k. A level 5 analysis of Pride and Prejudice, for example, would reveal that 'b' follows ''Eliza'' more frequently than any other character. After a level k analysis, you'd be able to produce random Pride and Prejudice by always choosing the next character based on the previous k characters and the probabilities revealed by the analysis. At only a moderate level of analysis (say, levels 5-7), the randomly generated text begins to take on many of the characteristics of the source text. It probably won't make complete sense, but you'll be able to tell that it was derived from Pride and Prejudice as opposed to, say, A Tale of Two Cities.
Getting Started
Use the Canvas Project Manager to download the starting point for PS5. You should end up with a Java project with a name of the form PS5_LASTNAME_FIRSTNAME. Alternatively, you can download PS5_Starting_Point.zip, import it into Eclipse, and rename the imported project.
In the new project you will find a package named books containing the complete text of two 19th century novels, Pride and Prejudice and A Tale of Two Cities. You will also find a package called cs1410 containing PS5Library.java and PS5LibraryTests.java. The source files each contain compilation errors because neither is complete.
In the PS5Library class I have provided a method, generateText, that implements the randomized text generation algorithm described above. It takes three parameters: a Scanner that should contain the complete text of a book, an integer that is the level of the analysis you wish to perform, and an integer that is the amount of text that you want to generate. If all of the parameters are valid, it returns randomly generated text of the requested length. However, if the level is greater than or equal to the length of the text, or if the level or length is negative, the method throws an IllegalArgumentException.
In addition, I have provided a main method that makes use of generateText to produce output based on Pride and Prejudice. The purpose of the main method is to illustrate the use of generateText. It is not essential to completing the assignment, so feel free to play around with it.
In the PS5LibraryTests class I have given one test for each of the four methods that you will be implementing. You will also be adding more test cases to the class.
This assignment has two parts. Be sure to complete both of them!
Part 1
My generateText method depends on four public static methods that are currently missing from PS5Library. Your first job is to implement and test them. They are:
scannerToString, which takes a Scanner as its parameter and returns a String. The returned string consists of all the characters in the scanner in their original order, including the newlines. The last line (assuming there are any lines) should always end with a newline, even if it didn't in the original text. For example, scannerToString("This is a test") should return "This is a test ". A convenient way to implement this method is to build up the result by reading one line at a time from the Scanner. For much improved efficiency when dealing with Scanners containing complete books, consider using a StringBuilder object to construct the result. You can look at my generateText method for an example of its use.
chooseSubstring, which takes a String text, an int length, and a random number generator as its parameters. It should use the random number generator to return a randomly chosen substring of text that has the specified length. If length is either negative or greater than the length of text, the method should throw an IllegalArgumentException. For example, chooseSubstring("abcde", 4, new Random()) should return "abcd" about half the time and "bcde" about half the time. A string of length n will contain n+1-m different substrings of length m, assuming n m. These substrings start at indexes ranging from 0 to n-m. There is a convenient method provided by the Random parameter that you can use to choose a random index.
getCharsThatFollowPattern, which takes a String text and a String pattern as parameters, and returns an ArrayList
pickCharThatFollowsPattern, which takes a String text, a String pattern, and a random number generator as parameters. It should randomly choose a non-tail occurrence of the pattern in the text, returning the character that immediately follows that occurrence of the pattern. If there are no non-tail occurrences of the pattern in the text, the method should throw a NoSuchElementException. For example, pickCharThatFollowsPattern("They are here", "he") should return 'y' or 'r' with equal probability. You should use your getCharsThatFollowPattern method in your implementation of this method. If you don't, you'll be wasting a lot of time.
You are to implement these four methods so that they behave exactly as specified. When you do this, you will pass the four tests contained in PS5LibraryTests and my generateText method will work as specified. Do not deviate from the specifications; do not modify generateText; do not modify the four tests.
In addition to implementing the four methods, you are to add additional test methods to PS5LibraryTests. The tests that it currently contains are only a starting point. You goal should be to thoroughly exercise all aspects of each method's specification, including the cases where exceptions are thrown.
You will benefit from adding these test cases in two ways. First, part of your grade will be based on the test cases that you add. Second, by thoroughly testing your methods, you are more likely to pass the test cases that we will use when we grade.
Part 2
When you are confident that your methods work properly and that you can generate random text with my generateText method, you can move on to the second step. Create a third class called Generator within the cs1410 package. This class should have a main method that provides a user interface for random text generation. Your interface should work as follows:
It should bring up an input dialog with which the user can enter the desired analysis level . The user should be repeatedly prompted until he or she enters an integer zero or higher. If the user cancels the dialog, the program should end.
It should bring up an input dialog with which the user can enter the desired length of the output text. The user should be repeatedly prompted until he or she enters an integer zero or higher. If the user cancels the dialog, the program should end.
It should bring up a file dialog with which the user can select a text file to be analyzed. The user should be repeatedly prompted until he or she selects a file that can be opened. If the user cancels the dialog at any point, the program should end.
If the text file turns out to contain fewer than level+1 characters, an appropriate error message should be displayed and then the program should end.
It should use the generateText method and the three inputs provided by the user to generate random text.
It should use a message dialog to display the generated text.
The program should then end.
Your program should handle gracefully all user errors. Under no circumstances should the program crash because of an unhandled exception.
If your program generates anything amusing or profound, please post it to the PS5 discussion forum. You can find lots of books in plain text format at the Project Gutenberg web site.
package cs1410;
import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.NoSuchElementException; import java.util.Random; import java.util.Scanner; import cs1410lib.Dialogs;
/** * A library of methods for implementing the random text generation algorithm described in PS5, Fall 2017. * * @author SeungHoon Lee and Joe Zachary */ public class PS5Library { /** * Demonstrates the use of the generateText method. */ public static void main (String[] args) throws IOException { // You won't need to use this feature in PS5, but this shows how to include a resource (in this // case a text file) as part of a project. I created a package called "books", then put two // text files into the package. I was then able to open one of those files as shown below. When // I export the project, the resources go along with it.
// get text book, and make Scanner to consume token. try (InputStream book = PS5Library.class.getResourceAsStream("/books/PrideAndPrejudice.txt"); Scanner input = new Scanner(book)) { System.out.println(generateText(input, 6, 100)); }
}
/** * Uses all the text in the input to generate and return random text with the specified level and length, using the * algorithm described in PS5, CS 1410, Fall 2017. * * @throws IllegalArgumentException if level
// Grab all the text from the Scanner and make sure it is long enough. String text = scannerToString(input); if (level >= text.length()) { throw new IllegalArgumentException(); }
// Create a random number generator to pass to the methods that make random choices Random rand = new Random();
// Get the initial pattern. String pattern = chooseSubstring(text, level, rand);
// Build up the final result one character at a time. We use a StringBuilder because // it is more efficient than using a String when doing long sequences of appends. StringBuilder result = new StringBuilder(); while (result.length()
// Update the pattern by removing its first character and adding on the new // character. The length of the pattern remains the same. If the pattern is // the empty string, though, it never changes.) if (pattern.length() > 0) { pattern = pattern.substring(1) + newChar; } } catch (NoSuchElementException e) { // It is possible to get stuck if the pattern occurs only once in the text and // that occurrence is at the very end of the text. In this case, we pick a new // seed and keep going. pattern = chooseSubstring(text, level, rand); } }
// Return the string we've accumulated. return result.toString(); }
/* * getCharsThatFollowPattern, which takes a String text and a String pattern as parameters, and returns an * ArrayList
public static ArrayList
int start = 0;
// loop end when is true while (true) {
int index = text.indexOf(pattern, start);
// handle error if (index
break;
}
if (index + pattern.length() == text.length()) {
// Sequence of tail
break;
}
list.add(text.charAt(index + 1));
start = index + 1;
}
return list;
}
/* * pickCharThatFollowsPattern, which takes a String text, a String pattern, and a random number generator as * parameters. It should randomly choose a non-tail occurrence of the pattern in the text, returning the character * that immediately follows that occurrence of the pattern. If there are no non-tail occurrences of the pattern in * the text, the method should throw a NoSuchElementException. For example, * pickCharThatFollowsPattern("They are here", "he") should return 'y' or 'r' with equal probability. * * You should use your getCharsThatFollowPattern method in your implementation of this method. If you don't, you'll * be wasting a lot of time. */
public static char pickCharThatFollowsPattern (String text, String pattern, Random rand) { // Make new arrayList ArrayList
// if statement to handle error if (tailChars.isEmpty()) // . { throw new NoSuchElementException(); } else { return tailChars.get(rand.nextInt(tailChars.size())); } }
/* * chooseSubstring, which takes a String text, an int length, and a random number generator as its parameters. It * should use the random number generator to return a randomly chosen substring of text that has the specified * length. If length is either negative or greater than the length of text, the method should throw an * IllegalArgumentException. For example, chooseSubstring("abcde", 4, new Random()) should return "abcd" about half * the time and "bcde" about half the time. * * A string of length n will contain n+1-m different substrings of length m, assuming n m. These substrings start * at indexes ranging from 0 to n-m. There is a convenient method provided by the Random parameter that you can use * to choose a random index. * */ public static String chooseSubstring (String text, int length, Random rand) { // if statement to handle error if (length text.length()) {
throw new IllegalArgumentException();
} else { int startIndex = rand.nextInt(text.length() - length + 1);
return text.substring(startIndex, startIndex + length); } }
/* * scannerToString, which takes a Scanner as its parameter and returns a String. The returned string consists of all * the characters in the scanner in their original order, including the newlines. The last line (assuming there are * any lines) should always end with a newline, even if it didn't in the original text. For example, * scannerToString("This is a test") should return "This is a test ". * * A convenient way to implement this method is to build up the result by reading one line at a time from the * Scanner. For much improved efficiency when dealing with Scanners containing complete books, consider using a * StringBuilder object to construct the result. You can look at my generateText method for an example of its use. */
public static String scannerToString (Scanner input) {
String result = "";
if (!input.hasNext()) { throw new NoSuchElementException(); } while (input.hasNext()) { result += input.nextLine() + " "; }
return result;
} }
----------------
package cs1410;
import static org.junit.Assert.*; import java.util.ArrayList; import java.util.NoSuchElementException; import java.util.Random; import java.util.Scanner; import org.junit.Test;
public class PS5LibraryTests { /** * This checks that the last line of the result ends with a newline, even if the last line in the scanner didn't. */ @Test public void testScannerToString1 () { assertEquals("This is a test ", PS5Library.scannerToString(new Scanner("This is a test"))); }
/** * This illustrates how to test that an exception is thrown when one is supposed to be thrown. If * pickCharThatFollowsPattern doesn't thrown the right kind of exception, the test will fail. */ @Test(expected = NoSuchElementException.class) public void testPickCharThatFollowsPattern () { PS5Library.pickCharThatFollowsPattern("hello", "o", new Random()); }
/** * This illustrates a way to do tests of methods that have a randomized behavior. When we ask for a randomly chosen * substring of length 4 of "abcde", about half the time we should get "abcd" and about half the time we should get * "bcde". So we call chooseSubstring 1000 times and count how many times we get each possibility. (If we get * anything else back, we immediately fail the test case.) Then we assert that we got each "about" half the time. It * is possible for a correct implementation to fail this test if we get extremely unlucky, but that is extremely * unlikely. */ @Test public void testChooseSubstring () { Random rand = new Random(); int abcd = 0; int bcde = 0;
for (int i = 0; i
assertTrue(400
/** * This illustrates how to make assertions about ArrayLists. */ @Test public void testGetCharsThatFollowPattern () { ArrayList
}
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started