Hello and thank you for reading. I have written a program to reverse the words in a string using a stack. I am to use 3 sentences and reverse each sentence separately. I have been able to reverse the entire string, which wasn't an issue. Then I changed my program so I am reading to the period and reversing the first sentence. However, I can't get it to read the next sentence. I believe I need a second loop but this is where I struggle. There are several questions/answers on this site that address this assignment, but none that have really taken the approach I have so they aren't relevant. At least, not from what I can tell. This is what I have:
for (String word : wordArray) {
if (word.endsWith(".") {
Stack.push(word.substring(0, word.length()-1));
break;
}
else {
Stack.push(word);
}
}
So my sentences are: "Cats are cool. Dogs are cool. So are turtles." My program will print:
"cool are Cats"
I know I need to append a period and I can figure that out later. I'm just struggling with how to create a second loop to continue reading the rest of the string.
What I need is: "cool are Cats. cool are Dogs. turtles are So."
You were thinking in the right direction: you do need one more loop to empty out the stack when the end of a sentence has been encountered, and you need some mean of storing the data (it could be an ArrayList, or a StringBuilder).
I would use a StringBuilder to store reversed sentences.
The logic of generating a reversed sentence by retrieving the elements from the stack can be extracted into a separate method. In a nutshell, it's while-loop that runs until the stack is not empty. To join the string back into a sentence, I would use a StringJoiner which facilitates combining the strings using a specified delimiter (feel free to reimplement this logic as you see fit, the point of this answer is to explain the algorithm and provide a source of inspiration rather than be a ready to go copy-past solution, for instance, you can use two StringJoiners instead of the combination StringJoiner + StringBuilder, I've only shown one possibility).
That's how it might be implemented:
public static String reverseSentences(String[] wordArray) {
Stack<String> stack = new Stack<>();
StringBuilder reversedSentences = new StringBuilder();
for (String word : wordArray) {
if (word.endsWith(".")) {
stack.push(word.substring(0, word.length() - 1));
reversedSentences
.append(createSentence(stack)) // appending the reversed sentence
.append(". "); // adding a period and a white space at the end of the sentence
} else {
stack.push(word);
}
}
return reversedSentences.toString();
}
public static String createSentence(Stack<String> stack) {
StringJoiner sentence = new StringJoiner(" "); // white space would be used a delimiter between the words
while (!stack.isEmpty()) {
sentence.add(stack.pop());
}
return sentence.toString();
}
main()
public static void main(String[] args) {
System.out.println(reverseSentences("Cats are cool. Dogs are cool. So are turtles.".split(" ")));
}
Output:
cool are Cats. cool are Dogs. turtles are So.
Before your loop, you need to create your stack like
Stack<String> wordStack = new Stack<String>();
You would do your current push operations on wordStack, and then you would pop in your second loop as you would expect.
You got very close.
Related
I have a very specific problem for my CS course. I have a sentence in a string, and I need that separated into individual words within an ArrayList, and cannot use the split method.
The issue I have is that I have had zero teaching on arrays, only the bare minimum teaching for loops and String statements. I've done a lot of research and figured out the best way to go about making the loop, and sending the words to the ArrayList, however I still can't find a good way to actually have it loop through the sentence and separate each individual word at all. I get how easily it can be done to separate the very first word, however after that I get lost. I have no idea how to make the loop for its other iterations specifically grab the next word in the sentence after the one it previously got.
(Note: The only utilities imported are Scanner, File, HashMap, ArrayList, Random, and *)
What I'm looking for is any tips of specific methods I should try and employ or research. Or perhaps a set of code that is fairly functional in doing something similar to what I'm looking for that I can look at and build my own code off of.
When you said the word "word"(That's weird) I assume that they are separated by spaces. If you are reading in the inputs, then just use Scanner... Then:
Scanner input = new Scanner(System.in);
ArrayList<String> words = new ArrayList<String>();
for(int i = 0;i<numberOfWord;i++){
words.add(input.next());// .next() method read data that are separated by space
}
or:
String theLineOfWord;//Given to you
StringTokenizer st = new StringTokenizer(theLinOfWord);//Used to separate words.
ArrayList<String> words = new ArrayList<String>();
while(st.hasMoreTokens()){
words.add(st.nextToken();
}
or:
public static ArrayList<String> getWords(String line){
ArrayList<String> words = new ArrayList<String>();
line += " ";//add a space to ignore the ending case
while(line.length() != 0) {
words.add(line.substring(0, line.indexOf(' ')));//add the word to the list
line = line.substring(line.indexOf(' ') + 1, line.length());//take out the useless string away
}
return words;
}
I've done HTML but that is nothing like learning java now in my AP class. So I'm pretty much brand new to coding. Today we learned about recursion and I'm pretty sure I understood it when it comes to using it like in this video.
https://www.youtube.com/watch?v=fpuWkZs51aM
But we then had to use it in a different way. We needed to make a program called WordPlay that accept any words, one at a time, until the word "STOP" is input. When stop was put in it prints them back out in reverse order. Here's the code.
import java.util.Scanner;
public class HelloWorld
{
public static void main(String[] args)
{
System.out.println("Enter list of words, one per line");
System.out.println("Final word should be STOP");
wordList();
}
public static void wordList()
{
Scanner keyboard = new Scanner(System.in);
String word = keyboard.next();
if (word.equalsIgnoreCase("STOP"))
System.out.println();
else
wordList();
System.out.println(word);
}
}
So the part that I don't understand is that this works fine but when I look at the ending of wordList() it seems to me that it would just keep repeating the last word that was input. I don't get what I'm missing. Can someone explain the logic here?
The recursion does output the word that was input, however each call to wordList gets a new local variable named word (each word value is on "the stack"). If you mark it final, nothing will complain - because the word isn't modified after initialization. Also, you should probably extract the Scanner (each invocation creates a new local one of those too).
public static void wordList()
{
Scanner keyboard = new Scanner(System.in);
final String word = keyboard.next(); // <-- this is the current word.
if (word.equalsIgnoreCase("STOP"))
System.out.println();
else
wordList(); // <-- it's not STOP, recurse... which
// will get a new local word (and print it).
System.out.println(word); // <-- however, this is still current word.
}
The function will execute from top to bottom as usual, but if it enters the else block it will jump back up to the beginning like shown below. It will 'loop' exactly like this until word equals "STOP", then it'll enter the if block, print out a new line (System.out.println()) then SKIP the else block, print out word then exit the function. Brackets in the if-else statement will make this easier to see.
public static void wordList()
{
|->Scanner keyboard = new Scanner(System.in);
|
| String word = keyboard.next();
| if (word.equalsIgnoreCase("STOP")) {
| System.out.println();
| }
| else {
|---wordList();
}
System.out.println(word);
}
Its basically a recursion function or method which calls itself again and again until if condition inside it is false.
So here first new word entered by user is stored in variable called word, then if condition will check if value stored in word is Stop, if its not then again wordlist method is called and all above process is repeated again.
So each time new values entered is stored in word variable.
Thats all!!
public static int wordList()
{
Scanner keyboard = new Scanner(System.in);
String word = keyboard.next();
if (word.equalsIgnoreCase("STOP"))
{
System.out.println();
return 0;
}
System.out.println(word);
return wordList();
}
Try this
This will be the sequence of operations
1) call wordlist()
2) Get a word, say WORD1 and store in local variable word.
3) before calling wordlist recursively, WORD1 goes into stack. Stack is something like a box where you can fill say biscuits one over an other, and you can take out the biscuit that you placed last. Now the stack has WORD1
4) get another word, say WORD2 and store in local variable word. This is a new function call, even if it is recursive. So a new local variable word is allocated memory.
5) before calling wordlist recursively, WORD2 goes into stack. So now WORD2 will be the top one and WORD1 will be below in the stack.
5) get another work, now it is STOP.
6) STOP is printed
7) function returns
8) now the flow returns to previous call. Now WORD2 is popped out of stack as the local variable holding WORD2 belongs to this instance of the recursive call.
8) print WORD2 and return to previous call. Now WORD1 is popped out of the stack as the local variable holding WORD1 belongs to this instance of the recursive call
9) WORD1 printed.
Just to tell you an analogy, let us assume you have a similar task. You have to get a set of books from a friend standing besides you. You have to give him back the books in the reverse order as you got it from him as soon as he gives you a book named stop.
1) You get the book from him
2) before getting the next book, you keep it on a table, since you cannot hold this and get more books from your friend
3) yet get the next book from him
4) before getting the next book, you keep it over the first book
5) you continue doing this until you get a book named stop
6) now you start returning the books, first you will return the book named stop and as you continue, since the books are stacked, you will be returning the book in reverse order.
Hope this clarifies.
It would just repeat that last word entered if the line System.out.println(word) was before the if statement.
To understand recursion, you need the notion of the "stack". Each call to wordList() occurs in a separate level in the stack. There is a different word variable in each of these stack levels.
Since the ``System.out.println(word)` line happen after the recursive call, each of these are executed when un-piling the stack (i.e. after the previous level returns). That's why words appear in reverse order. Image: if you pile boxes one atop the other, when you un-pile them, the last box is the first to go out (hence the acronym LIFO=Last In First Out).
Another important concept for recursion is to have a way of stopping it (i.e. prevent infinite recursion). In this program, it is done when the user enters "STOP".
I like to think of these problems as a 'call stack'. Each time you 'call' the method recursively you add another 'stack'. Every recursive method needs a stopping case. In your problem the first occurrence of the word 'STOP' (how convenient) acts as your stopping case.
For example if someone enters:
"Fox"
"Bear"
"Deer"
"STOP"
As soon as the word "STOP" appears, it will be printed. Now we pick up where we left off in your 'call stack' which is the ending of
wordList()
Now the only step left is
System.out.println(word)
The word 'Deer' will be printed and now our list being printed is:
"STOP"
"Deer"
And so forth until we reach the last word.
I'm trying to break a text into its various paragraphs. I did find this question and this question. However, I've already figured out how to detect the paragraphs. I'm having trouble saving them.
One morning, when Gregor Samsa woke from troubled dreams, he found
himself transformed in his bed into a horrible vermin. He lay on
his armour-like back, and if he lifted his head a little he could
see his brown belly, slightly domed and divided by arches into stiff
sections. The bedding was hardly able to cover it and seemed ready
to slide off any moment. His many legs, pitifully thin compared
with the size of the rest of him, waved about helplessly as he
looked.
"What's happened to me?" he thought. It wasn't a dream. His room,
a proper human room although a little too small, lay peacefully
between its four familiar walls. A collection of textile samples
The text above would be counted as two paragraphs. Below is the function that I am using for paragraph detection.
public List<Paragraph> findParagraph(List<String> originalBook)
{
List<Paragraph> paragraphs = new LinkedList<Paragraph>();
List<String> sentences = new LinkedList<String>();
for(int i=0;i<originalBook.size();i++)
{
//if it isn't a blank line
//don't count I,II symbols
if(!originalBook.get(i).equalsIgnoreCase("") & originalBook.get(i).length()>2)
{
sentences.add(originalBook.remove(i));
//if the line ahead of where you are is a blank line you've reach the end of the paragraph
if(i < originalBook.size()-1)
{
if(originalBook.get(i+1).equalsIgnoreCase("") )
{
Paragraph paragraph = new Paragraph();
List<String> strings = sentences;
paragraph.setSentences(strings);
paragraphs.add(paragraph);
sentences.clear();
}
}
}
}
return paragraphs;
}
And this is the class that defines my Paragraph
public class Paragraph
{
private List<String> sentences;
public Paragraph()
{
super();
}
public List<String> getSentences() {
return sentences;
}
public void setSentences(List<String> sentences) {
this.sentences = sentences;
}
}
I'm able to detect the paragraphs fine, but I'm clearing all of the sentences and I'm getting a list that only contains the last paragraph. I've been trying to think of a solution and I haven't been able to come up with one. Can anybody offer any advice?
I've tried to be as thorough as possible in my explanation. I can add more details if necessary.
The issue is in this block:
Paragraph paragraph = new Paragraph();
List<String> strings = sentences; // <-- !!!!!
paragraph.setSentences(strings);
paragraphs.add(paragraph);
sentences.clear();
You use the same object that sentences points to for all your paragraphs, so in the end all your Paragraph objects will point to the same List<String>. Thus, any change you make to sentences will alter that single List<String>, and the changes will be seen across all your Paragraph objects, as they all refer to the same instance.
It's a little like if sentences were a balloon, what you're doing is giving all your Paragraph objects a string leading to that balloon (plus another string leading back to sentences). If one of those objects (or the sentences reference) decides to follow the string and pop the balloon, everyone will see the change.
The solution is simple. Skip sentences.clear() and simply use List<String> strings = new LinkedList<>() instead of List<String> strings = sentences. That way, all your Paragraph objects will have distinct List<String> objects that hold their sentences, and changes you make to any one of them will be independent of the other. If you do that, you can skip declaring sentences at the beginning of the method too.
You can change your code to be more efficient and clean, rather than calculating its index and creating multiple if statements.
sample:
Scanner scan = new Scanner(new File("text.txt"));
String parag = "";
while(scan.hasNextLine())
{
String s = scan.nextLine();
if(s.trim().length() != 0)
parag += s + "\n"; //new sentence
else
{
System.out.println(parag); //new paragraph
parag = "";
}
}
System.out.println(parag); //last paraggraph
I'm currently working on an anagram solver. I saw a really good post which had one recommendation on alphabetizing the letters of both the user input and dictionary list before comparing. It seemed interesting so I'm giving it a try. Previously I used permutations, but I want something that I can eventually (and efficiently) use to solve multi word anagrams.
I can put both my user input and dictionary into char arrays and sorting alphabetically. Now I need to compare each so I can determine if something is an anagram or not. I thought about taking the alphabetized user input and determining if the alphabetized dictionary contained it or not. I've posted my code below. As you can guess I'm a little confused on the logic of this process. I was wondering if someone could help me straighten out the logic a little. Thanks for any help.
public class AnagramSolver1 {
public static void main(String[] args) throws IOException {
List<String> dictionary = new ArrayList<String>();
List<String> inputList = new ArrayList<String>();
BufferedReader in = new BufferedReader(new FileReader("src/dictionary.txt"));
String line = null;
Scanner scan = new Scanner(System.in);
while (null!=(line=in.readLine())){
dictionary.add(line);
}
in.close();
char[] sortDictionary;
char[] inputSort;
System.out.println("Enter Word: ");
String input = scan.next();
inputList.add(input);
//Getting a little confused here. I thought about sorting my input
//then iterating through my dictionary (while sorting it too) and comparing
//thus far it produces nothing
for(int i = 0; i < inputList.size(); i++){
inputSort = inputList.get(i).toCharArray();
Arrays.sort(inputSort);
for (int j = 0; j < dictionary.size(); j++) {
sortDictionary = dictionary.get(i).toCharArray();
Arrays.sort(sortDictionary);
if(inputSort.equals(sortDictionary)){
System.out.println("Anagram" +dictionary.get(i));
} //end if
}//end for
}//end for
}//end main
}
Why not maintain a Map<String, Set<String>> that maps a sorted-character string to a set of strings that are its anagrams. You can update this map as you read words from the dictionary. For example, if you read the word dog you would add an entry to the map "dgo" => {"dog"} (notice that dgo consists of the sorted characters of the word dog). Then if you read the word god, you would sort its characters to obtain the same dgo and consequently amend the previous entry to be "dgo" => {"dog", "god"}. You would of course repeat this for every word in the dictionary.
This should allow for quick and easy querying. If you wanted to then find anagrams of the word dog you would use map.get(sortChars("dog")).
On another note, I'm going to reiterate what the other answer mentioned, namely that it's important to modularize your code. You should put logically related functions/tasks in their own methods as opposed to having everything in one place. This helps with readability and your/others' ability to maintain your code in the future.
You are doing too many things at once here. You've got file IO, user input, sorting and the algorithm all in one place. Try to modularize it so you have a function called isAnagram(List<Character> firstPhrase, List<Character> secondPhrase). Make sure that works correctly, then have all the other steps figure out how to call it. This way you can test your algorithm without requiring user input. This will be a much faster feedback loop.
It's algorithm will work like this:
(optionally) copy the contents of the input so you don't mutate the input
compare their lengths. If they're not equal, return false
sort each list
iterate element by element and check if they're equal. If they're not, return false
if you reach the end, return true.
For my assignment I've had to create an ArrayStack, a StackADT, and now I have to make a program to take in a string and output it in reverse.
Now this sounds simple, but I have no idea how to push something into the array. I've been googling the shit out of this and can't find an actual answer that makes sense.
Specifically I'm having trouble linking the main program to the actual array, and then linking the input string to the push().
public class ReverseSentenceMain {
public static void main (String[] args)
{
AssignmentArrayStack stack = new AssignmentArrayStack();
//private AssignmentArrayStack<String> stack;
public ReverseSentenceMain()
{
stack = new AssignmentArrayStack<Integer>();
}
String sentence;
String result = null;
String words;
stack = (T[])(new Object[initialCapacity]);
Scanner in = new Scanner(System.in);
System.out.println("Enter a sentence");
}
}
I'd appreciate any help and thanks for your time
You start scanning by calling next on the scanner.
sentence = in.next();
Then you perform a split on whitespace to divide up the sentence into tokens that you push into your stack. The scanner can do the split for you I think. Look at the Scanner JavaDoc or String JavaDoc for more information.
You should format the code. Press ctrl+K or use the little 101010 icon.
Anyways. The stack class should have a push method. You need to get the sentence. You could loop through the sentence and then push the characters onto a stack. Once you do that, then you can pop the characters off to print the string in reverse order.
loop through string
stack.push(string[i])
while(currChar = stack.pop())
print currChar (or store to another variable)
I believe that will work. Been a while since ive done anything in java.
A stack isn't really an array. Its more like a linked list. It adds an element as the first element in a linked list and then updates the pointer.
Acutally heres a decent example http://www.javacoffeebreak.com/faq/faq0037.html
And i just noticed you want to reverse the sentence and not the word, so do what willcodejavaforfood said and tokenize it with scanner. I remember you can do this. It will read up every whitespace. you get that token and add it to the stack. Some kind of type of concept though.