Counting sentences, only sentences ending with punctuation + 2 spaces - java

I'm trying to figure out how to make a sentence counter, which I have, but the thing is, I need it to count a sentence ONLY when two spaces come after the period/question mark/etc.
For example, with the code I have, if you enter the string "hello, my name is ryan..." it returns the count of 3 sentences. I need it to only count one sentence.
This program needs to count words also. I count the words by taking the amount of spaces - 1. This is where my problem lies, I either mess up the word count or the sentence count.
Here is the method for the word count:
public static int countWords(String str){
if(str == null || str.isEmpty())
return 0;
int count = 0;
for(int i = 0; i < str.length(); i++){
if(str.charAt(i) != ' '){
count++;
while(str.charAt(i) != ' ' && i < str.length()-1){
i++;
}
}
}
return count;
}
And here is the method for counting sentences:
public static int sentenceCount(String str) {
String SENTENCE_ENDERS = ".?!";
int sentenceCount=0;
int lastIndex=0;
for(int i=0;i < str.length(); i++){
for(int j=0;j < SENTENCE_ENDERS.length(); j++){
if(str.charAt(i) == SENTENCE_ENDERS.charAt(j)){
if(lastIndex != i-1){
sentenceCount++;
}
lastIndex = i;
}
}
}
return sentenceCount;
}

I actually got it, using regex, was super simple also.
public static int sentenceCount(String str) {
String regex = "[?|!|.]+[ ]+[ ]";
Pattern p = Pattern.compile(regex);
int count = 0;
Matcher m = p.matcher(str);
while (m.find()) {
count++;
}
if (count == 0){
return 1;
}
else {
return count + 1;
}
}
Works great, I added the if statement assuming user is inputting at least one sentence, and added one to the count assuming they won't put two spaces at the end of their last sentence.

Related

why are some words not checked or included in string of reversed words?

everyone. I have a task- reverse every word in a sentence as long as the word is 5 or more letters long. The program has been working with most words, but after a couple, the words are not included. Does anyone know why this is happening? Here is the code:
public static int wordCount(String str) {
int count = 0;
for(int i = 0; i < str.length(); i++) if(str.charAt(i) == ' ') count++;
return count + 1;
}
This just gets the word count for me, which I use in a for loop later to loop through all the words.
public static String reverseString(String s) {
Stack<Character> stack = new Stack<>();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
stack.push(s.charAt(i));
}
while (!stack.empty()) {
sb.append(stack.pop());
}
return sb.toString();
}
This reverses a single string. This is not where I reverse certain words- this reverses a string. "Borrowed" from https://stackoverflow.com/a/33458528/16818831.
Lastly, the actual function:
public static String spinWords(String sentence) {
String ans = "";
for(int i = 0; i <= wordCount(sentence); i++) {
if(sentence.substring(0, sentence.indexOf(' ')).length() >= 5) {
ans += reverseString(sentence.substring(0, sentence.indexOf(' '))) + " ";
sentence = sentence.substring(sentence.indexOf(' ') + 1);
} else {
ans += sentence.substring(0, sentence.indexOf(' ')) + " ";
sentence = sentence.substring(sentence.indexOf(' ') + 1);
}
}
return ans;
}
This is where my mistake probably is. I'd like to know why some words are omitted. Just in case, here is my main method:
public static void main(String[] args) {
System.out.println(spinWords("Why, hello there!"));
System.out.println(spinWords("The weather is mighty fine today!"));
}
Let me know why this happens. Thank you!
The main issue would appear to be the for loop condition in spinWords()
The word count of your sentence keeps getting shorter while at the same time, i increases.
For example:
i is 0 when the word count is 5
i is 1 when the word count is 4
i is 2 when the word count is 3
i is 3 when the word count is 2 which
stops the loop.
It can't get through the whole sentence.
As many have mentioned, using the split method would help greatly, for example:
public static String spinWords(String sentence) {
return Arrays.asList(sentence.split(" ")).stream()
.map(word -> word.length() < 5 ? word : new StringBuilder(word).reverse().toString())
.collect(Collectors.joining(" "));
}
I think you should rewrite a lot of your code using String.split(). Instead of manually parsing every letter, you can get an array of every word just by writing String[] arr = sentence.split(" "). You can then use a for loop to go through and reverse each word something like this
for (int i=0; i<arr.length; i++) {
if (arr[i] >= 5) {
arr[i] = reverse(arr[i])
}
}
I know you just asked for a solution to your current code, but this would probably get you a better grade :)

Check endings of an String without built-in methods like endsWith() in Java

I want to check if every word in an string has specific endings with various length. I can't use arrays & methods for this like endsWith(). The only methods im allowed to use are charAt() and length().
public class TextAnalyse {
public static void main(String[] args) {
System.out.println(countEndings("This is a test", "t"));
System.out.println(countEndings("Waren sollen rollen", "en"));
System.out.println(countEndings("The ending is longer then every single word", "abcdefghijklmn"));
System.out.println(countEndings("Today is a good day", "xyz"));
System.out.println(countEndings("Thist is a test", "t"));
System.out.println(countEndings("This is a test!", "t"));
System.out.println(countEndings("Is this a test?", "t"));
}
public static int countEndings(String text, String ending) {
int counter = 0;
int counting;
int lastStringChar;
for (int i = 0; i < text.length(); i++) {
lastStringChar = 0;
if (!(text.charAt(i) >= 'A' && text.charAt(i) <= 'Z' || text.charAt(i) >= 'a' && text.charAt(i) <= 'z') || i == text.length() - 1) {
if( i == text.length() - 1 ){
lastStringChar = 1;
}
counting = 0;
for (int j = 0; j + lastStringChar < ending.length() && i > ending.length(); j++) {
if (text.charAt(i - ending.length() + j + lastStringChar) == ending.charAt(j)) {
counting = 1;
} else {
counting = 0;
}
}
counter += counting;
}
}
return counter;
}
}
The actual results are that I get one counting less, I guess its because it dont check the last chars properly.
The most simple solution I can come up with is the following:
Check, if a word ends with a given suffix:
public static boolean endsWith(String word, String suffix) {
if(suffix.length() > word.length()) {
return false;
}
int textIndex = (word.length() - 1);
int suffixIndex = (suffix.length() - 1);
while(suffixIndex >= 0) {
char textChar = word.charAt(textIndex);
char suffixChar = suffix.charAt(suffixIndex);
if(textChar != suffixChar) {
return false;
}
textIndex--;
suffixIndex--;
}
return true;
}
Split the given in its' words and use the above method to count every word ending with the given ending:
public static int countEndings(String text, String ending) {
{
//maybe remove punctuation here...
//(if yes, use String.replace for example)
}
String[] words = text.split(" ");
int counter = 0;
for(String word: words) {
if(endsWith(word, ending)) {
counter++;
}
}
return counter;
}
Also consider to remove unwanted punctuation, like '!' or '?' (...) - the above implementation will not recognize count any word ending with t in the String test!!
I guess you are able to use regular expression.
If you want count words with ending, you can use the following code:
public static int countEndings(String text, String ending) {
final Matcher wordWithEndMatches = Pattern.compile("\\b[A-Za-z]*" + ending + "\\b").matcher(text);
int count = 0;
while(wordWithEndMatches.find()) {
count++;
}
return count;
}

Find n:th word in a string

I'm trying to find nth word in a string. I am not allowed to use StringToknizer or split method from String class.
I now realize that I can use white space as a separator. The only problem is I don't know how to find the location of the first white space.
public static String pick(String message, int number){
String lastWord;
int word = 1;
String result = "haha";
for(int i=0; i<message.length();i++){
if(message.charAt(i)==' '){enter code here
word++;
}
}
if(number<=word && number > 0 && number != 1){//Confused..
int space = message.indexOf(" ");//improve
int nextSpace = message.indexOf(" ", space + 1);//also check dat
result = message.substring(space,message.indexOf(' ', space + 1));
}
if(number == 1){
result = message.substring(0,message.indexOf(" "));
}
if(number>word){
lastWord = message.substring(message.lastIndexOf(" ")+1);
return lastWord;
}
else return result;
}
The current implementation is overcomplicated, hard to understand.
Consider this alternative algorithm:
Initialize index = 0, to track your position in the input string
Repeat n - 1 of times:
Skip over non-space characters
Skip over space characters
At this point you are at the start of the n-th word, save this to start
Skip over non-space characters
At this point you are just after the end of the n-th word
Return the substring between start and end
Like this:
public static String pick(String message, int n) {
int index = 0;
for (int i = 1; i < n; i++) {
while (index < message.length() && message.charAt(index) != ' ') index++;
while (index < message.length() && message.charAt(index) == ' ') index++;
}
int start = index;
while (index < message.length() && message.charAt(index) != ' ') index++;
return message.substring(start, index);
}
Note that if n is higher than there are words in the input,
this will return empty string.
(If that's not what you want, it should be easy to tweak.)
CHEAT (using regex)1
public static String pick(String message, int number){
Matcher m = Pattern.compile("^\\W*" + (number > 1 ? "(?:\\w+\\W+){" + (number - 1) + "}" : "") + "(\\w+)").matcher(message);
return (m.find() ? m.group(1) : null);
}
Test
System.out.println(pick("This is a test", 1));
System.out.println(pick("! This # is # a $ test % ", 3));
System.out.println(pick("This is a test", 5));
Output
This
a
null
1) Only StringTokenizer and split are disallowed ;-)
This needs some edge case handling (e.g. there are fewer than n words), but here's the idea I was getting at. This is similar to your solution, but IMO less elegant than janos'.
public static String pick(String message, int n) {
int wordCount = 0;
String word = "";
int wordBegin = 0;
int wordEnd = message.indexOf(' ');
while (wordEnd >= 0 && wordCount < n) {
word = message.substring(wordBegin, wordEnd).trim();
message = message.substring(wordEnd).trim();
wordEnd = message.indexOf(' ');
wordCount++;
}
if (wordEnd == -1 && wordCount + 1 == n) {
return message;
}
if (wordCount + 1 < n) {
return "Not enough words to satisfy";
}
return word;
}
Most iteration in Java can now be replaced by streams. Whether this is an improvement is a matter of (strong) opinion.
int thirdWordIndex = IntStream.range(0, message.size() - 1)
.filter(i -> Character.isWhiteSpace(message.charAt(i)))
.filter(i -> Character.isLetter(message.charAt(i + 1)))
.skip(2).findFirst()
.orElseThrow(IllegalArgumentException::new) + 1;

Reverse characters in a sentence

Im trying to reverse characters in a sentence without using the split function. Im really close but I am missing the final letter. Can some one please point me in the right direction? Right now it prints "This is a new sentence" as "sihT si a wen cnetnes" Also I included if(start == 0) because the program would skip the initial space character, but I don't understand why?
static String reverseLetters(String sentence)
StringBuilder reversed = new StringBuilder("");
int counter = 0;
int start = 0;
String word;
for(int i = 0; i <= sentence.length()-1 ; i++ )
{
if(sentence.charAt(i)== ' '|| i == sentence.length()-1 )
{
StringBuilder sb = new StringBuilder("");
sb.append(sentence.substring(start,i));
if(start == 0)
{
start = i;
word = sb.toString();
reversed.append(reverseChar(word));
reversed.append(' ');
}
else
{
start = i;
word = sb.toString();
reversed.append(reverseChar(word));
}
}
return reversed.toString();
}
static String reverseChar (String word)
{
StringBuilder b = new StringBuilder("");
for(int idx = word.length()-1; idx >= 0; idx -- )
{
b.append(word.charAt(idx));
}
return b.toString();
}
start means wordStart. As i points to the space, the next wordStart should point after i.
Hence the last i should point after the last word char, should be length()
the if-then-else is too broad; a space has to be added in one case: i pointing at the space.
One could loop unconditionally, and on i == length() break in the middle of the loop code.
I think the error lies in the index, the for should be
for(int i = 0; i <= sentence.length() ; i++ )
Then if should be:
if (sentence.charAt(i==0?0:i-1)== ' '|| i == sentence.length() )
For me the error will be that the substring(start,i) for the last one i should be sentence.length instead of sentence.length-1, so this would solve it.
Substring is open in the last index, so if you put substring(1, 10) will be substring from 1 to 9. That might be the problem with last word.
The thing with the first space is also the problem with substring, let's say you're reading "this is..." the first time it will do a subtring with start=0 and i = 4 so you expect "this " but it really is "this". The next reading, with start=4 and i=7 will be " is".
So with the change of the index you should be able to remove the if/else with start==0 too.
Another option
private String reverse (String originalString) {
StringBuilder reverseString = new StringBuilder();
for (int i = originalString.length() - 1; i >= 0; i--) {
reverseString.append(originalString.charAt(i));
}
return reverseString.toString();
}
String reverseString = "This is a new sentence";
System.out.println(new StringBuffer(reverseString).reverse().toString());
Syso prints : ecnetnes wen a si sihT
Put
i <= sentence.length()
In your for loop and change the if to:
if(i == sentence.length() || sentence.charAt(i)== ' ')
as
substring(start,i)
Returns the string up to i, not included.
import java.util.Stack;
public class Class {
public static void main(String[] args) {
String input = "This is a sentence";
char[] charinput = input.toCharArray();
Stack<String> stack = new Stack<String>();
for (int i = input.length() - 1; i >= 0; i--) {
stack.push(String.valueOf(charinput[i]));
}
StringBuilder StackPush = new StringBuilder();
for (int i = 0; i < stack.size(); i++) {
StackPush.append(stack.get(i));
}
System.out.println(StackPush.toString());
}
}
Not a split to be seen.

Find the Number of Occurrences of a Substring in a String

Why is the following algorithm not halting for me?
In the code below, str is the string I am searching in, and findStr is the string occurrences of which I'm trying to find.
String str = "helloslkhellodjladfjhello";
String findStr = "hello";
int lastIndex = 0;
int count = 0;
while (lastIndex != -1) {
lastIndex = str.indexOf(findStr,lastIndex);
if( lastIndex != -1)
count++;
lastIndex += findStr.length();
}
System.out.println(count);
How about using StringUtils.countMatches from Apache Commons Lang?
String str = "helloslkhellodjladfjhello";
String findStr = "hello";
System.out.println(StringUtils.countMatches(str, findStr));
That outputs:
3
Your lastIndex += findStr.length(); was placed outside the brackets, causing an infinite loop (when no occurence was found, lastIndex was always to findStr.length()).
Here is the fixed version :
String str = "helloslkhellodjladfjhello";
String findStr = "hello";
int lastIndex = 0;
int count = 0;
while (lastIndex != -1) {
lastIndex = str.indexOf(findStr, lastIndex);
if (lastIndex != -1) {
count++;
lastIndex += findStr.length();
}
}
System.out.println(count);
A shorter version. ;)
String str = "helloslkhellodjladfjhello";
String findStr = "hello";
System.out.println(str.split(findStr, -1).length-1);
The last line was creating a problem. lastIndex would never be at -1, so there would be an infinite loop. This can be fixed by moving the last line of code into the if block.
String str = "helloslkhellodjladfjhello";
String findStr = "hello";
int lastIndex = 0;
int count = 0;
while(lastIndex != -1){
lastIndex = str.indexOf(findStr,lastIndex);
if(lastIndex != -1){
count ++;
lastIndex += findStr.length();
}
}
System.out.println(count);
Do you really have to handle the matching yourself ? Especially if all you need is the number of occurences, regular expressions are tidier :
String str = "helloslkhellodjladfjhello";
Pattern p = Pattern.compile("hello");
Matcher m = p.matcher(str);
int count = 0;
while (m.find()){
count +=1;
}
System.out.println(count);
I'm very surprised no one has mentioned this one liner. It's simple, concise and performs slightly better than str.split(target, -1).length-1
public static int count(String str, String target) {
return (str.length() - str.replace(target, "").length()) / target.length();
}
Here it is, wrapped up in a nice and reusable method:
public static int count(String text, String find) {
int index = 0, count = 0, length = find.length();
while( (index = text.indexOf(find, index)) != -1 ) {
index += length; count++;
}
return count;
}
String str = "helloslkhellodjladfjhello";
String findStr = "hello";
int lastIndex = 0;
int count = 0;
while((lastIndex = str.indexOf(findStr, lastIndex)) != -1) {
count++;
lastIndex += findStr.length() - 1;
}
System.out.println(count);
at the end of the loop count is 3; hope it helps
public int countOfOccurrences(String str, String subStr) {
return (str.length() - str.replaceAll(Pattern.quote(subStr), "").length()) / subStr.length();
}
A lot of the given answers fail on one or more of:
Patterns of arbitrary length
Overlapping matches (such as counting "232" in "23232" or "aa" in "aaa")
Regular expression meta-characters
Here's what I wrote:
static int countMatches(Pattern pattern, String string)
{
Matcher matcher = pattern.matcher(string);
int count = 0;
int pos = 0;
while (matcher.find(pos))
{
count++;
pos = matcher.start() + 1;
}
return count;
}
Example call:
Pattern pattern = Pattern.compile("232");
int count = countMatches(pattern, "23232"); // Returns 2
If you want a non-regular-expression search, just compile your pattern appropriately with the LITERAL flag:
Pattern pattern = Pattern.compile("1+1", Pattern.LITERAL);
int count = countMatches(pattern, "1+1+1"); // Returns 2
You can number of occurrences using inbuilt library function:
import org.springframework.util.StringUtils;
StringUtils.countOccurrencesOf(result, "R-")
Increment lastIndex whenever you look for next occurrence.
Otherwise it's always finding the first substring (at position 0).
The answer given as correct is no good for counting things like line returns and is far too verbose. Later answers are better but all can be achieved simply with
str.split(findStr).length
It does not drop trailing matches using the example in the question.
public int indexOf(int ch,
int fromIndex)
Returns the index within this string of the first occurrence of the specified character, starting the search at the specified index.
So your lastindex value is always 0 and it always finds hello in the string.
try adding lastIndex+=findStr.length() to the end of your loop, otherwise you will end up in an endless loop because once you found the substring, you are trying to find it again and again from the same last position.
Try this one. It replaces all the matches with a -.
String str = "helloslkhellodjladfjhello";
String findStr = "hello";
int numberOfMatches = 0;
while (str.contains(findStr)){
str = str.replaceFirst(findStr, "-");
numberOfMatches++;
}
And if you don't want to destroy your str you can create a new string with the same content:
String str = "helloslkhellodjladfjhello";
String strDestroy = str;
String findStr = "hello";
int numberOfMatches = 0;
while (strDestroy.contains(findStr)){
strDestroy = strDestroy.replaceFirst(findStr, "-");
numberOfMatches++;
}
After executing this block these will be your values:
str = "helloslkhellodjladfjhello"
strDestroy = "-slk-djladfj-"
findStr = "hello"
numberOfMatches = 3
As #Mr_and_Mrs_D suggested:
String haystack = "hellolovelyworld";
String needle = "lo";
return haystack.split(Pattern.quote(needle), -1).length - 1;
Based on the existing answer(s) I'd like to add a "shorter" version without the if:
String str = "helloslkhellodjladfjhello";
String findStr = "hello";
int count = 0, lastIndex = 0;
while((lastIndex = str.indexOf(findStr, lastIndex)) != -1) {
lastIndex += findStr.length() - 1;
count++;
}
System.out.println(count); // output: 3
Here is the advanced version for counting how many times the token occurred in a user entered string:
public class StringIndexOf {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Enter a sentence please: \n");
String string = scanner.nextLine();
int atIndex = 0;
int count = 0;
while (atIndex != -1)
{
atIndex = string.indexOf("hello", atIndex);
if(atIndex != -1)
{
count++;
atIndex += 5;
}
}
System.out.println(count);
}
}
This below method show how many time substring repeat on ur whole string. Hope use full to you:-
String searchPattern="aaa"; // search string
String str="aaaaaababaaaaaa"; // whole string
int searchLength = searchPattern.length();
int totalLength = str.length();
int k = 0;
for (int i = 0; i < totalLength - searchLength + 1; i++) {
String subStr = str.substring(i, searchLength + i);
if (subStr.equals(searchPattern)) {
k++;
}
}
This solution prints the total number of occurrence of a given substring throughout the string, also includes the cases where overlapping matches do exist.
class SubstringMatch{
public static void main(String []args){
//String str = "aaaaabaabdcaa";
//String sub = "aa";
//String str = "caaab";
//String sub = "aa";
String str="abababababaabb";
String sub = "bab";
int n = str.length();
int m = sub.length();
// index=-1 in case of no match, otherwise >=0(first match position)
int index=str.indexOf(sub), i=index+1, count=(index>=0)?1:0;
System.out.println(i+" "+index+" "+count);
// i will traverse up to only (m-n) position
while(index!=-1 && i<=(n-m)){
index=str.substring(i, n).indexOf(sub);
count=(index>=0)?count+1:count;
i=i+index+1;
System.out.println(i+" "+index);
}
System.out.println("count: "+count);
}
}
Matcher.results()
You can find the number of occurrences of a substring in a string using Java 9 method Matcher.results() with a single line of code.
It produces a Stream of MatchResult objects which correspond to captured substrings, and the only thing needed is to apply Stream.count() to obtain the number of elements in the stream.
public static long countOccurrences(String source, String find) {
return Pattern.compile(find) // Pattern
.matcher(source) // Mather
.results() // Stream<MatchResults>
.count();
}
main()
public static void main(String[] args) {
System.out.println(countOccurrences("helloslkhellodjladfjhello", "hello"));
}
Output:
3
here is the other solution without using regexp/patterns/matchers or even not using StringUtils.
String str = "helloslkhellodjladfjhelloarunkumarhelloasdhelloaruhelloasrhello";
String findStr = "hello";
int count =0;
int findStrLength = findStr.length();
for(int i=0;i<str.length();i++){
if(findStr.startsWith(Character.toString(str.charAt(i)))){
if(str.substring(i).length() >= findStrLength){
if(str.substring(i, i+findStrLength).equals(findStr)){
count++;
}
}
}
}
System.out.println(count);
If you need the index of each substring within the original string, you can do something with indexOf like this:
private static List<Integer> getAllIndexesOfSubstringInString(String fullString, String substring) {
int pointIndex = 0;
List<Integer> allOccurences = new ArrayList<Integer>();
while(fullPdfText.indexOf(substring,pointIndex) >= 0){
allOccurences.add(fullPdfText.indexOf(substring, pointIndex));
pointIndex = fullPdfText.indexOf(substring, pointIndex) + substring.length();
}
return allOccurences;
}
public static int getCountSubString(String str , String sub){
int n = 0, m = 0, counter = 0, counterSub = 0;
while(n < str.length()){
counter = 0;
m = 0;
while(m < sub.length() && str.charAt(n) == sub.charAt(m)){
counter++;
m++; n++;
}
if (counter == sub.length()){
counterSub++;
continue;
}
else if(counter > 0){
continue;
}
n++;
}
return counterSub;
}
🍑 Just a little more peachy answer
public int countOccurrences(String str, String sub) {
if (str == null || str.length() == 0 || sub == null || sub.length() == 0) return 0;
int count = 0;
int i = 0;
while ((i = str.indexOf(sub, i)) != -1) {
count++;
i += sub.length();
}
return count;
}
I was asked this question in an interview just now and I went completely blank. (Like always, I told myself that the moment the interview ends ill get the solution) which I did, 5 mins after the call ended :(
int subCounter=0;
int count =0;
for(int i=0; i<str.length(); i++) {
if((subCounter==0 && "a".equals(str.substring(i,i+1)))
|| (subCounter==1 && "b".equals(str.substring(i,i+1)))
|| (subCounter==2 && "c".equals(str.substring(i,i+1)))) {
++subCounter;
}
if(subCounter==3) {
count = count+1;
subCounter=0;
}
}
System.out.println(count);

Categories

Resources