How to reverse the words in a sentence, but not punctuation using recursion. The sentence is said to use punctuation marks: ,.?!
Input: "Jack, come home!"
Output: "home, come Jack!"
Now I have somehow managed to complete the task correctly but without using recursion.
How should I convert this work to use recursion to solve the problem?
Here's the method:
public static StringBuilder reverseSentenceWithPunctuation(String sentence, int i) {
String[] parts = sentence.split(" ");
StringBuilder newSentence = new StringBuilder();
Map<Integer, Character> punctuationMap = new HashMap<>();
for (int j = 0; j < parts.length; j++) {
if (parts[j].endsWith(",") || parts[j].endsWith(".") || parts[j].endsWith("!") || parts[j].endsWith("?")) {
char lastSymbol = parts[j].charAt(parts[j].length()-1);
punctuationMap.put(j, lastSymbol);
String changedWord = parts[j].replace(String.valueOf(lastSymbol), "");
parts[j] = changedWord;
}
}
for (int j = parts.length-1; j >= 0; j--) {
newSentence.append(parts[j]);
if (punctuationMap.containsKey(i)) {
newSentence.append(punctuationMap.get(i));
newSentence.append(" ");
} else
newSentence.append(" ");
i++;
}
return newSentence;
}
Thanks in advance!
To implement this task using recursion, a pattern matching the first and the last words followed by some delimiters should be prepared:
word1 del1 word2 del2 .... wordLast delLast
In case of matching the input the result is calculated as:
wordLast del1 REVERT(middle_part) + word1 delLast
Example implementation may be as follows (the words are considered to contain English letters and apostrophe ' for contractions):
static Pattern SENTENCE = Pattern.compile("^([A-Za-z']+)([^A-Za-z]+)?(.*)([^'A-Za-z]+)([A-Za-z']+)([^'A-Za-z]+)?$");
public static String revertSentence(String sentence) {
Matcher m = SENTENCE.matcher(sentence);
if (m.matches()) {
return m.group(5) + (m.group(2) == null ? "" : m.group(2))
+ revertSentence(m.group(3) + m.group(4)) // middle part
+ m.group(1) + (m.group(6) == null ? "" : m.group(6));
}
return sentence;
}
Tests:
System.out.println(revertSentence("Jack, come home!"));
System.out.println(revertSentence("Jack, come home please!!"));
System.out.println(revertSentence("Jane cried: Will you come home Jack, please, don't go!"));
Output:
home, come Jack!
please, home come Jack!!
go don't: please Jack home come you, Will, cried Jane!
I don't think this is a good case for a recursive function, mainly because you need 2 loops. Also, in general, iterative algorithms are better performance-wise and won't throw a stackoverflow exception.
So I think the main reasons to work with recursive functions is readability and easiness, and honestly, in this case, I think it isn't worth it.
In any case, this is my attempt to convert your code to a recursive function. As stated before, I use 2 functions because of the 2 loops. I'm sure there is a way to achieve this with a single function that first loads the map of punctuations and then compose the final String, but to be honest that would be quite ugly.
import java.util.*;
import java.util.stream.*;
public class HelloWorld{
static Character[] punctuationCharacters = {',','.','!'};
public static void main(String []args){
System.out.println(reverseSentenceWithPunctuation("Jack, come home!"));
}
private static String reverseSentenceWithPunctuation(String sentence) {
String[] parts = sentence.split(" ");
return generate(0, parts, extractPunctuationMap(0, parts));
}
private static Map<Integer, Character> extractPunctuationMap(int index, String[] parts){
Map<Integer, Character> map = new HashMap<>();
if (index >= parts.length) {
return map;
}
char lastSymbol = parts[index].charAt(parts[index].length() - 1);
if (Arrays.stream(punctuationCharacters).anyMatch(character -> character == lastSymbol)) {
parts[index] = parts[index].substring(0, parts[index].length() - 1);
map = Stream.of(new Object[][] {
{ index, lastSymbol}
}).collect(Collectors.toMap(data -> (Integer) data[0], data -> (Character) data[1]));
}
map.putAll(extractPunctuationMap(index + 1, parts));
return map;
}
private static String generate(int index, String[] parts, Map<Integer, Character> punctuationMap) {
if (index >= parts.length) {
return "";
}
String part = index == 0? " " + parts[index] : parts[index];
if (punctuationMap.containsKey(parts.length -1 - index)) {
part += punctuationMap.get(parts.length -1 - index);
}
return generate(index + 1, parts, punctuationMap) + part;
}
}
In pseudocode maybe something like that:
take the whole sentence
(a). get the first word
(b). get the last word
(if there is a punctuation after the first or last word, leave it there)
swap(a, b) and return the remaining middle of the sentence
repeat (1) and (2) until there is only two words or one
return the last two (swapped) words left (if one word, just return that)
Related
I have a string as follows:
String sentence = "I have bananas\r" +
"He has apples\r" +
"I own 3 cars\n" +
"*!"
I'd like to reverse this string so as to have an output like this:
"*!" +
"\ncars 3 own I" +
"\rapples has He" +
"\rbananas have I"
Here is a program I wrote.
public static String reverseWords(String sentence) {
StringBuilder str = new StringBuilder();
String[] arr = sentence.split(" ");
for (int i = arr.length -1; i>=0; i--){
str.append(arr[i]).append(" ");
}
return str.toString();
}
But I don't get the output as expected. What is wrong?
The problem is you are only splitting on spaces, but that is not the only type of whitespace in your sentence. You can use the pattern \s to match all whitespace. However, then you don't know what to put back in that position after the split. So instead we will split on the zero-width position in front of or behind a whitespace character.
Change your split to this:
String[] arr = sentence.split("(?<=\\s)|(?=\\s)");
Also, now that you are preserving the whitespace characters, you no longer need to append them. So change your append to this:
str.append(arr[i]);
The final problem is that your output will be garbled due to the presence of \r. So, if you want to see the result clearly, you should replace those characters. For example:
System.out.println(reverseWords(sentence).replaceAll("\\r","\\\\r").replaceAll("\\n","\\\\n"));
This modified code now give the desired output.
Output:
*!\ncars 3 own I\rapples has He\rbananas have I
Note:
Since you are freely mixing \r and \n, I did not add any code to treat \r\n as a special case, which means that it will be reversed to become \n\r. If that is a problem, then you will need to prevent or undo that reversal.
For example, this slightly more complex regex will prevent us from reversing any consecutive whitespace characters:
String[] arr = sentence.split("(?<=\\s)(?!\\s)|(?<!\\s)(?=\\s)");
The above regex will match the zero-width position where there is whitespace behind but not ahead OR where there is whitespace ahead but not behind. So it won't split in the middle of consecutive whitespaces, and the order of sequences such as \r\n will be preserved.
The logic behind this question is simple, there are two steps to achieve the OP's target:
reverse the whole string;
reverse the words between (words splitted by spaces);
Instead of using StringBuilder, I'd prefer char[] to finish this, which is easy to understand.
The local test code is:
public class WordReverse {
public static void main(String... args) {
String s = " We have bananas\r" +
"He has apples\r" +
"I own 3 cars\n" +
"*!";
System.out.println(reverseSentenceThenWord(s));
}
/**
* return itself if the #param s is null or empty;
* #param s
* #return the words (non-whitespace character compound) reversed string;
*/
private static String reverseSentenceThenWord(String s) {
if (s == null || s.length() == 0) return s;
char[] arr = s.toCharArray();
int len = arr.length;
reverse(arr, 0, len - 1);
boolean inWord = !isSpace(arr[0]); // used to track the start and end of a word;
int start = inWord ? 0 : -1; // is the start valid?
for (int i = 0; i < len; ++i) {
if (!isSpace(arr[i])) {
if (!inWord) {
inWord = true;
start = i; // just set the start index of the new word;
}
} else {
if (inWord) { // from word to space, we do the reverse for the traversed word;
reverse(arr, start, i - 1);
}
inWord = false;
}
}
if (inWord) reverse(arr, start, len - 1); // reverse the last word if it ends the sentence;
String ret = new String(arr);
ret = showWhiteSpaces(ret);
// uncomment the line above to present all whitespace escape characters;
return ret;
}
private static void reverse(char[] arr, int i, int j) {
while (i < j) {
char c = arr[i];
arr[i] = arr[j];
arr[j] = c;
i++;
j--;
}
}
private static boolean isSpace(char c) {
return String.valueOf(c).matches("\\s");
}
private static String showWhiteSpaces(String s) {
String[] hidden = {"\t", "\n", "\f", "\r"};
String[] show = {"\\\\t", "\\\\n", "\\\\f", "\\\\r"};
for (int i = hidden.length - 1; i >= 0; i--) {
s = s.replaceAll(hidden[i], show[i]);
}
return s;
}
}
The output is not in my PC as OP provided but as:
*!
bananas have I
However, if you set a breakpoint and debug it and check the returned string, it will be as:
which is the right answer.
UPDATE
Now, if you would like to show the escaped whitespaces, you can just uncomment this line before returning the result:
// ret = showWhiteSpaces(ret);
And the final output will be exactly the same as expected in the OP's question:
*!\ncars 3 own I\rapples has He\rbananas have I
Take a look at the output you're after carefully. You actually need two iteration steps here - you first need to iterate over all the lines backwards, then all the words in each line backwards. At present you're just splitting once by space (not by new line) and iterating over everything returned in that backwards, which won't do what you want!
Take a look at the example below - I've kept closely to your style and just added a second loop. It first iterates over new lines (either by \n or by \r, since split() takes a regex), then by words in each of those lines.
Note however this comes with a caveat - it won't preserve the \r and the \n. For that you'd need to use lookahead / lookbehind in your split to preserve the delimiters (see here for an example.)
public static String reverseWords(String sentence) {
StringBuilder str = new StringBuilder();
String[] lines = sentence.split("[\n\r]");
for (int i = lines.length - 1; i >= 0; i--) {
String[] words = lines[i].split(" ");
for (int j = words.length - 1; j >= 0; j--) {
str.append(words[j]).append(" ");
}
str.append("\n");
}
return str.toString();
}
In my country there is Game Show called Slagalica where one of the tasks is to find longest word in array of 12 letters. Size of the longest word is always 10, 11 or 12.
I have file with words from my language I use as database. Words that have 10, 11 or 12 letters in them I've saved in List (listWordSize10_11_12).
When I enter jumbled word [12 letters] in I want from my program to find what word is that originally. I know how to make it work when jumbled word is 12 letters word but I can't work it out when it's less.
Example: 10 letter word is jumbled + 2 random letters.
Goal is for that 10 letter word to be recognized and printed in original state.
Where is what I've done:
// un-jumbling word
System.out.println("Unesite rijec koja treba da se desifruje: ");
String jumbledWord = tast.nextLine();
char[] letter = jumbledWord.toCharArray();
Arrays.sort(letter);
String sorted_Mistery_Word = new String(letter);
for (int i = 0; i < listWordSize10_11_12.size(); i++) {
int exception = 0;
char[] letter_2 = listWordSize10_11_12.get(i).toCharArray();
Arrays.sort(letter_2);
String longWords = new String(letter_2);
int j = i;
while(longWords.length()>i){
if(sorted_Mistery_Word.charAt(j)!=longWords.charAt(i)){
exception++;
j++;
}
}
if(exception < 3){
System.out.println("Your word is: "+listWordSize10_11_12.get(i));
break;
}
}
Thanks!!!
P.S. This is not a homework or some job, just project I've been doing for fun!
Thanks everyone for the help, I've learned a lot!
Your basic approach for 12 characters, which I would characterize as fingerprinting, will also work for 10 or 11 letter words with some modification.
That is, rather that just sorting the letters in each candidate word as you examine it to create the fingerprint, pre-process your array to create a small(ish) fingerprint of each word as a byte[]. Using the English alphabet and ignoring case, for example, you could create a 26-byte array for each word, where each byte position contained the count of each letter in the word.
That is fingerprint[0] contains the number of 'a' characters in the word, and fingerprint[25] the number of 'z' characters.
Then just replace your sorted_Mistery_Word.charAt(j)!=longWords.charAt(i) check with a loop that increments a temporary array for each letter in the mystery word. Finally, check that the temporary array has at least the same value for every position. Something like:
byte [] makeFingerprint(String s) {
byte[] fingerprint = new byte[26];
for (char c : letter_2) {
fingerprint[c - 'a']++;
}
return fingerprint;
}
/** determine if sub is a subset of super */
boolean isSubset(byte[] sub, byte[] super) {
for (int i=0; i < sub.length; i++) {
if (sub[i] > super[i])
return false;
}
return true;
}
void findMatch(String jumbledWord) {
byte[] fingerprint = makeFingerprint(jumbledWord);
for (byte[] candidate : fingerprintList) {
if (isSubset(fingerprint, candidate)) {
System.out.println("Your word is: " + ...);
break;
}
}
}
Here I omitted the creation of the fingerprintList - but it just involves fingerprint each word.
There are plenty of optimizations possible, but this should already be quite a bit faster than your version (and is "garbage free" in the main loop). It can handle candidates of any length (not just 10-12 chars). The biggest optimization, if you will check many words, is to try to use the "fingerpint" as a key for direct lookup. For the 12 character case this is trivial (direct lookup), but for the 10 and 11 or this you would likely have to use type of technique for higher-dimensional searching - locality sensitive hashing seems like a natural fit.
Here's one way to go about the problem. Let's say (since no example input was provided) that there's 3 String[]'s, arr3 (that represents the 10-letter-words you have), arr4 (that represents the 11-letter-words you have), and arr5 (you guessed it, represents the 12-letter words you have). This is what I made for those:
String[] arr3 = { "map", "cat", "dog" };
String[] arr4 = { "four", "five", "nine" };
String[] arr5 = { "funny", "comma", "brace" };
So based on what you said, if we got the input of pam, we'd want the output of map. If we got the input of enni we'd want the output of nine. And if we got the input of yfunn we'd want the output of funny. So how to go about doing this? I like what #cricket_007 mentioned about using maps. But first, let's get the permutations down.
Based off of the linked SO question, I came up with this modified/variation to get the jumbled text:
public static List<String> jumble(String str) {
List<String> result = new ArrayList<String>();
permutation(result, "", str);
return result;
}
private static void permutation(List<String> l, String prefix, String s) {
int n = s.length();
if (n == 0) {
l.add(prefix);
} else {
for (int i = 0; i < n; i++)
permutation(l, prefix + s.charAt(i), s.substring(0, i) + s.substring(i + 1, n));
}
}
This code will let us easily construct a single map for us to store jumbled text in as a key, and the answer to that jumbled text as a value.
All together, the final code looks like this:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Appy {
public static void main(String[] args) {
String[] arr3 = { "map", "cat", "dog" };
String[] arr4 = { "four", "five", "nine" };
String[] arr5 = { "funny", "comma", "brace" };
List<String> permutations = new ArrayList<String>();
Map<String, String> map = new HashMap<String, String>();
for (String s : arr3) {
permutations = jumble(s);
for (String str : permutations)
map.put(str, s);
}
for (String s : arr4) {
permutations = jumble(s);
for (String str : permutations)
map.put(str, s);
}
for (String s : arr5) {
permutations = jumble(s);
for (String str : permutations)
map.put(str, s);
}
System.out.println("test = 'pam' -> " + map.get("pam"));
System.out.println("test = 'enni' -> " + map.get("enni"));
System.out.println("test = 'yfunn' -> " + map.get("yfunn"));
}
public static List<String> jumble(String str) {
List<String> result = new ArrayList<String>();
permutation(result, "", str);
return result;
}
private static void permutation(List<String> l, String prefix, String s) {
int n = s.length();
if (n == 0) {
l.add(prefix);
} else {
for (int i = 0; i < n; i++)
permutation(l, prefix + s.charAt(i), s.substring(0, i) + s.substring(i + 1, n));
}
}
}
Which gives the resulting output of:
test = 'pam' -> map
test = 'enni' -> nine
test = 'yfunn' -> funny
Now applying this logic, adapting for your case of 10, 11, and 12 letter words should be relatively simple. Cheers!
I know I'm missing some things and that's what I really need help with. The code doesn't work in all cases and am looking for help improving/fixing it.
Assignment:
The code I have so far:
public String word(int num, String words)
{
int l = words.indexOf(" ");
int r = words.indexOf(" ", l+1);
for(int i = 3; i <= num; i++){
l = r;
r = words.indexOf(" ", l+1);
//if(i != num)
// l = r;
}
String theword = words.substring(l,r);
return theword;
}
}
As this is clearly homework, I will give you text only.
Your approach may work eventually, but it is laborious and overly complicated, so it's hard to debug and hard to get right.
make use of String's API by using the split() method
after splitting the sentence into an array of word Strings, return the element at num less one (array are indexed starting at zero
check the length of the array first, in case there are less words than num, and take whatever action you think is appropriate in that case
For part 2, a solution in a simple form may be:
create a new blank string for the result
iterate over the characters of the given string adding the character to the front of the result string
make use of String's toUpperCase() method
Since this is homework and you have showed some effort. This is how you can do part 1 of your question. This code is pretty evident.
1) I am returning null if number is greater than the number of words in string as we dont want user to enter 5 when there are only 2 words in a string
2) Splitting the string by space and basically returning the array with the number mentioned by user
There are more conditions which you must figure out such as telling the user to enter a number of the string length since it would not give him any result and taking input from Scanner instead of directy adding input in method.
public static String word(int num, String words)
{
String wordsArr[] = words.split(" ");
if(num <= 0 || num > wordsArr.length) return null;
return (wordsArr[num-1]);
}
the second part of your question must be attempted by you.
Well... not often you see people coming here with homework AND showing effort at the same time so bravo :).
This is example of how you can split the string and return the [x] element from that string
public class SO {
public static void main(String[] args) throws Exception {
int number = 3;
String word = "Hello this is sample code";
SO words = new SO();
words.returnWord(number, word);
}
private void returnWord(int number, String word) throws Exception {
String[] words = word.split("\\s+");
int numberOfWords = words.length;
if(numberOfWords >= number) {
System.out.println(words[number-1]);
} else {
throw new Exception("Not enought words!!!");
}
}
}
Yes it is a working example but do not just copy and paste that for your homework - as simple question from teacher - What is this doing, or how this works and your out :)! So understand the code, and try to modify it in a way that you are familiar what is doing what. Also its worth getting some Java book - and i recommend Head first Java by O'Really <- v.good beginner book!
if you have any questions please do ask!. Note that this answer is not 100% with what the textbook is asking for, so you can modify this code accordingly.
As of part 2. Well what Bohemian said will also do, but there is a lot quicker solution to this.
Look at StringBuilder(); there is a method on it that will be of your interest.
To convert String so all letter are upper case you can use .toUpperCase() method on this reversed string :)
You can try:
public class trial {
public static void main(String[] args)
{
System.out.println(specificword(0, "yours faithfully kyobe"));
System.out.println(reverseString("derrick"));}
public static String specificword(int number, String word){
//split by space
String [] parts = word.split("\\ ");
if(number <= parts.length){
return parts[number];
}
else{
return "null String";
}
}
public static String reverseString(String n){
String c ="";
for(int i = n.length()-1; i>=0; i--){
char m = n.charAt(i);
c = c + m;
}
String m = c.toUpperCase();
return m;
}
}
For the first problem, I'll give you two approaches (1. is recommended):
Use the String.split method to split the words up into an array of words, where each element is a word. Instead of one string containing all of the words, such as "hello my name is Michael", it will create an array of the words, like so [hello, my, name, is, Michael] and that way you can use the array to access the words. Very easy:
public static String word(int num, String words)
{
// split words string into array by the spaces
String[] wordArray = words.split(" "); // or = words.split("\\s+");
// if the number is within the range
if (num > 0 && num <= wordArray.length) {
return wordArray[num - 1]; // return the word from the word array
} else { // the number is not within the range of words
return null;
}
}
Only use this if you cannot use arrays! Loop through the word until you have found enough spaces to match the word you want to find:
public static String word(int num, String words)
{
for (int i = 0; i < words.length(); i++) { // every character in words
if (words.substring(i, i+1).equals(" ")) { // if word is a space
num = num - 1; // you've found the next word, so subtract 1 (number of words left is remaining)
}
if (num == 1) { // found all words
// return this word
int lastIndex = i+1;
while (lastIndex < words.length()) { // until end of words string
if (words.substring(lastIndex, lastIndex+1).equals(" ")) {
break;
}
lastIndex = lastIndex + 1; // not a space so keep moving along the word
}
/*
// or you could use this to find the last index:
int lastIndex = words.indexOf(" ", i + 1); // next space after i+1
if (lastIndex == -1) { // couldn't find another space
lastIndex = words.length(); // so just make it the last letter in words
}*/
if (words.substring(i, i+1).equals(" ")) { // not the first word
return words.substring(i+1, lastIndex);
} else {
return words.substring(i, lastIndex);
}
}
}
return null; // didn't find word
}
As for the second problem, just iterate backwards through the string and add each letter to a new string. You add each letter from the original string to a new string, but just back to front. And you can use String.toUpperCase() to convert the string to upper case. Something like this:
public static String reverse(String str) {
String reversedString = ""; // this will be the reversed string
// for every character started at the END of the string
for (int i = str.length() - 1; i > -1; i--) {
// add it to the reverse string
reversedString += str.substring(i, i+1);
}
return reversedString.toUpperCase(); // return it in upper case
}
I was asked this recently, and I couldn't figure out the best way. We are trying to replicate Google's search results where the search terms are bolded (using a b tag) in the results.
Input Terms Output
The search is cool {sea} The <b>sea</b>rch is cool
Originally, I thought this was pretty easy:
String results(String input, String[] terms)
{
for(String term : terms)
{
input = input.replace(term, "<b>" + term + "</b>");
}
return input;
}
However, this isn't correct. For example:
Input Terms Output
The search is cool {sea, search} The <b>search</b> is cool
I struggled to figure out the best way to approach this. Obviously we can no longer find and replace immediately. I played around with using a Map<Integer,String> where the key is the term and the value is the index returned by input.indexOf(term), but this seemed potentially unnecessary. Any improvements?
public String results(String input, String[] terms)
{
Map<Integer, String> map = new HashMap<Integer,String>();
for(String term : terms)
{
int index = input.indexOf(term);
if(index >= 0)//if found
{
String value = map.get(index);
if(value == null || value.length() < term.length())//use the longer term
map.put(index, term);
}
}
for(String term: map.values())
{
input = input.replace(term, "<b>" + term + "</b>");
}
return input;
}
Try this
import java.net.*;
import java.util.HashMap;
import java.util.Map;
import java.io.*;
public class main {
public static String results(String input, String[] terms)
{
for(String t : terms)
{
input = input.replace(t, "<b>" + t + "</b>");
}
return input;
}
public static void main(String[] args) {
String [] terms={"sea", "search"};
String s = results("The search is cool ",terms);
System.out.println(s);
String [] terms2={"search", "sea"};
String s2 = results("The search is cool ",terms2);
System.out.println(s2);
}
}
Output
The <b>sea</b>rch is cool
The <b><b>sea</b>rch</b> is cool
In your code you were adding two times the string in the same index in the hash map so it was actually replacing "sea" to 'search" in the hash map itself.because the index is 4 in the both the cases.
Map<Integer, String> map = new HashMap<Integer,String>();
for(String term : terms)
{
int index = input.indexOf(term);
if(index >= 0)//if found
{
String value = map.get(index); //the index is 4 here both the times
if(value == null || value.length() < term.length())
map.put(index, term);//so first time putting string sea at index 4 and in second iteration replacing "sea" to "search" at the same index 4 in hashmap because you want a longer term
}
}
for(String term: map.values())//here getting only one string which is "search"
{
input = input.replace(term, "<b>" + term + "</b>");
}
But if you want a longer term than it is working fine in your code itself.
You might do it with regular expressions.
public static String results(String input, String[] terms) {
String output = input;
Arrays.sort(terms);
for (int i = terms.length - 1; i >= 0; --i) {
String term = terms[i];
output = output.replaceAll("(?<!>)\\b" + term, "<b>" + term + "</b>");
}
// With regular expressions.
// \\b = word boundary, starting at words
// (?<X) = without preceding X (negative look-behind)
// Converting " searching " to " <b>search</b>ing ",
// Not converting " research ".
return output;
}
The solution is a reverse sort, so that "search" precedes "sea", and checking that no ">" precedes the word (= already replaced; with a longer term).
I have added a word boundary check, that is, terms should be at the beginning of words. Not necessary.
Mind the array parameter terms gets sorted.
I'm a newbie Java Developer. I want to write code to count the number of palindrome words in the paragraph using Java.
The assumptions are : User can enter a paragraph containing as many sentences as possible. Each word is separated by a whitespace, and each sentence is separated by a period and The punctuation right before or after the word will be ignored, while the punctuation inside the word will be counted.
Sample Input : Otto goes to school. Otto sees a lot of animals at the pets store.
Sample output : Otto = 2 a = 1 Sees = 1
Read the file into your program, split the entries at every space and enter those into an arraylist. Afterwards, apply your palindrome algorithm onto each value in your arraylist and keep track of the words that were a palindrome and their occurences (for example a 2D array, or an arraylist with an object that holds both values).
When you've followed these steps, you should pretty much be there. More specific help will probably be given once you've shown attempts of your own.
Using Collections in java will reduce the programming effort
Algorithm :
Read the paragraph to a String variable
Split the String using StringTokenizer using token as ' '(space) and add each word to ArrayList (Set wont allow duplicates)
Write a method which return boolean (TRUE/ FALSE) value based on whether a given String is palindrome or not.
Define a Map to hold the values of palindrome String and number of times it is repeated.
If yes
add the String to Map with key as palindrome String and value as number of times
else
dont add the String to Map
Repeat the same logic until all the words are finished
Sample Code:
` public class StringPalindromeCalculator {
private Map<String, int> wordsMap = new HashMap<>();
private List<String> wordsList = new ArrayLiat<>();
private boolean isPalindrome(String inputString) {
// write String palindrome logic here
}
public Map<String, int> findPalindromeWords(String completeString) {
StringTokenizer wordTokenizer = new StringTokenizer(completeString, ' ');
while(wordTokenizer.hasMoreTokens()) {
wordsList.add(wordTokenizer.nextToken());
}
for(String word : wordsList) {
if(isPalindrome(word)) {
if(wordsMap.containsKey(word)) {
// increment the value of word
}
} else {
// put the word into Map and return the map value
}
}
return wordsMap;
}
}`
Hope this Helps :)
public class Palindrome {
int count = 0;
public static void main(String[] args) {
String a = "malayalammadyoydaraarasdasdkfjasdsjhtj";
Palindrome palindrome = new Palindrome();
palindrome.countPalin(a);
}
private int countPalin(String str) {
for (int i = 0; i < str.length() - 1; i++) {
char start = str.charAt(i);
String st = "";
st += start;
for (int j = i + 1; j < str.length(); j++) {
st += str.charAt(j);
StringBuffer rev = new StringBuffer(st).reverse();
if (st.equals(rev.toString()) && st.length() > 1) {
System.out.println(st.toString());
count++;
}
}
st = "";
}
System.out.println("Total Count : " + count);
return count;
}
}