Word count on Java - java

How can I count the words of a sentence given as string? We are allowed to use only the following: for loops, if statemant, while, charAt, length().
I wrote this code:
public static int getWordCount()
{
String data = "bla bla bla bla";
int Count = 0;
for (int i=0; i<data.length(); i++)
{
if (data.charAt(i) != ' ')
Count ++;
}
return Count;
}
But it counts only the letters and not the words.

Here's a suggestion: Count the number of ' ' and add 1?
Example:
"bla bla bla bla"
1 2 3 : 3 + 1 = 4
"hello"
: 0 + 1 = 1
If you want to get fancy you could keep a boolean variable named something like lastWasSpace, set it to true when running into a space, setting it to false when you run into a non-space character. If you only increment the Count when lastWasSpace is false, you'll be able to handle strings with multiple consecutive spaces as well.
"bla bla bla"
1 2 : 2 + 1 = 3
lastWasSpace: FFFFTTTFFFFTTTTTFFFF

the given code would indeed count letters and not words. You may want to change the condition to:
if (data.charAt(i) == ' ')
this means, if you find a space, this would mark the beginning of the next word. Also, the last word will not be counted so you should return Count+1 instead of Count.
There are several assumptions I made here:
There will be exactly one space in between words.
There will not be any leading or trailing spaces.
To consider multiple spaces between words, you would need to modify the code a little. Instead of checking if a character is space, check to see if a character is non-space and the previous character was either a space or no character for the case of first word. This would also handle leading and trailing spaces.

public class Main {
public static void main(String[] args) {
String data = "This is a Test";
int wordCount = 1;
int charCount = 0;
for (int i = 0; i < data.length(); i++) {
if (data.charAt(i) == ' ') {
wordCount++;
} else {
charCount++;
}
}
System.out.println("wordCount = " + wordCount);
System.out.println("charCount = " + charCount);
}
}

String ss = " leading spaces in string ";
String[] sa = ss.trim().split("\\w+");
System.out.println(sa.length);
Note the use of trim to handle surrounding whitespace.

Use the below code for count the words in the line,
int index = 0;
int numWords =0;
boolean prevwhitespace = true;
String line = "bla bla bla bla";
while(index < line.length())
{
char c = line.charAt(index++);
boolean currwhitespace = Character.isWhitespace(c);
if(prevwhitespace && !currwhitespace)
{
numWords++;
}
prevwhitespace= currwhitespace;
}
System.out.println("no. of words in the line :: " +numWords);

My solution:
public static int getWordCount() {
String data = "bla bla bla bla";
String[] arr = data.split(" ");
return arr.length;
}

String s = "Aljohani Abdallah";
int counter = 1;
for (int i = 0; i < s.length() - 1; i++) {
if (s.charAt(i) == ' ' && s.charAt(i + 1) != ' ')
counter++;
}
if (s == " ")
counter = 0;
System.out.println(counter);
this code above here is count number of words in String so the first thing I have to know is length of the string and then we do if condition, if i was in index equals space at the same time must the letter after space not equal space the add 1 to counter
the end if the String was empty the counter should be zero.

String str = " Hello there my name is Bill ";
str = str.trim();
int count = 0;
for(int i = 0; i<str.length(); i++) {
if(str.charAt(i) == ' ' && str.charAt(i-1) != ' ') {
count++;
}
}
System.out.println(count+1);

Related

Find word in User Content without using .split() or StringTokenizer

I'm working on a program that ask the user to input a phrase and an integer. The integer is used to identify which word will be return from the phrase. For example, if they enter 5, the program should return to the user the fifth word in the sentence.
System.out.println("Your word is: " +combineString(phrase,numWord));
This is my work so far, there is a main to output,
public static String combineString(String newPhrase, int newNum) {
int countWords = 0;
String word = "";
//words count. I'll +1 everytime using countWord the match the amount of words
for(int i=0; i< newPhrase.length(); i++) {
if(newPhrase.charAt(i) == ' ') {
countWords++;
}
}
//return the last word. Ex: 15 words in a phrase if user pick the 18th word it will return the 15th word.
if(countWords+1 < newNum || countWords+1 <= newNum) {
word += newPhrase.substring(newPhrase.lastIndexOf(' ')+1, newPhrase.length()-1);
}
else if(newNum <=0) { //return null if the user pick 0 or less than 0
word += null;
}
return word;
And I was thinking a lot on how to work on the middle part and my thought are if the user pick numWord = 5, then in order to return the fifth word in that sentence, I'm gonna need to use "newPhrase.substring(space 4th +1, space 5th)". And this is where I stuck because I don't know how to start, and how to get to space 4th.
public static String combineString(String newPhrase, int newNum) {
if(newNum<=0)
return null;
String word = "";
String [] match = new String[newNum];
int j =0;
for(int i=0; i< newPhrase.length(); i++) {
word = word + newPhrase.charAt(i);
if(newPhrase.charAt(i) == ' ') {
match[j] = word;
if(j+1 == newNum) {
return word; // returns the specified word
}
j++;
word = "";
}
}
return word; //returns last word
}
This code should work for you. If that's the case accept the answer.
If you want to go really low level, then you can go lower than subString and operate on single characters. This way its easy to skip other characters than blank. Its also a step towards the way regular expression get executed by transforming them to finite state automatons.
enum ScanState {WHITESPACE, WORD}
private final static Set<Character> whitespace = new HashSet<>(Arrays.asList('"', ',', '.', '?', '!', '-', ';', ' '));
#Test
public void testTokenize() {
char[] text = "No, it's been \"yes?\", and not \"no!\" - hasn't it?".toCharArray();
List<String> expected = Arrays.asList("No", "it's", "been", "yes", "and", "not", "no", "hasn't", "it");
assertEquals(expected, tokenize(text));
}
private List<String> tokenize(char[] text) {
List<String> result = new ArrayList<String>();
char[] word = new char[256];
int maxLetter = 0;
ScanState prevState = ScanState.WHITESPACE;
for (char currentChar : text) {
ScanState currState = whitespace.contains(currentChar) ? ScanState.WHITESPACE : ScanState.WORD;
if (prevState == ScanState.WORD && currState == ScanState.WORD) {
word[maxLetter++] = currentChar;
}
if (prevState == ScanState.WORD && currState == ScanState.WHITESPACE) {
word[maxLetter++] = currentChar;
result.add(String.valueOf(word, 0, maxLetter - 1));
}
if (prevState == ScanState.WHITESPACE && currState == ScanState.WORD) {
maxLetter = 0;
word[maxLetter++] = currentChar;
}
prevState = currState;
}
return result;
}

Reverse every 2nd word of a sentence

I am trying to reverse every 2nd words of every single sentence like
If a given string is :
My name is xyz
The desired output should be :
My eman is zyx
My current output is:
Ym eman s1 zyx
I am not able to achieve my desired output.Don't know what I am doing wrong here
Here is my code
char[] sentence = " Hi my name is person!".toCharArray();
System.out.println(ReverseSentence(sentence));
}
private static char[] ReverseSentence(char[] sentence)
{
//Given: "Hi my name is person!"
//produce: "iH ym eman si !nosrep"
if(sentence == null) return null;
if(sentence.length == 1) return sentence;
int startPosition=0;
int counter = 0;
int sentenceLength = sentence.length-1;
//Solution handles any amount of spaces before, between words etc...
while(counter <= sentenceLength)
{
if(sentence[counter] == ' ' && startPosition != -1 || sentenceLength == counter) //Have passed over a word so upon encountering a space or end of string reverse word
{
//swap from startPos to counter - 1
//set start position to -1 and increment counter
int begin = startPosition;
int end;
if(sentenceLength == counter)
{
end = counter;
}
else
end = counter -1;
char tmp;
//Reverse characters
while(end >= begin){
tmp = sentence[begin];
sentence[begin] = sentence[end];
sentence[end] = tmp;
end--; begin++;
}
startPosition = -1; //flag used to indicate we have no encountered a character of a string
}
else if(sentence[counter] !=' ' && startPosition == -1) //first time you encounter a letter in a word set the start position
{
startPosition = counter;
}
counter++;
}
return sentence;
}
If you want to reverse the alternate word you can try something like splitting the whole String into words delimited by whitespaces and apply StringBuilder reverse() on every second word like :-
String s = "My name is xyz";
String[] wordsArr = s.split(" "); // broke string into array delimited by " " whitespace
StringBuilder sb = new StringBuilder();
for(int i = 0 ; i< wordsArr.length; i++){ // loop over array length
if(i%2 == 0) // if 1st word, 3rd word, 5th word..and so on words
sb.append(wordsArr[i]); // add the word as it is
else sb.append(new StringBuilder(wordsArr[i]).reverse()); // else use StringBuilder revrese() to reverse it
sb.append(" ");// add a whitespace in between words
}
System.out.println(sb.toString().trim()); //remove extra whitespace from the end and convert StringBuilder to String
Output :- My eman is zyx
You can solve your problem vary easy way! Just use a flag variable which will indicate the even or odd position, more precisely whether any word will gonna be reversed or not!
Look at the following modification I made in your code, just added three extra line:
private static boolean flag = true;// added a variable flag to check if we reverse the word or not.
private static char[] ReverseSentence(char[] sentence)
{
//Given: "Hi my name is person!"
//produce: "iH ym eman si !nosrep"
if(sentence == null) return null;
if(sentence.length == 1) return sentence;
int startPosition=0;
int counter = 0;
int sentenceLength = sentence.length-1;
//Solution handles any amount of spaces before, between words etc...
while(counter <= sentenceLength)
{
if(sentence[counter] == ' ' && startPosition != -1 || sentenceLength == counter) //Have passed over a word so upon encountering a space or end of string reverse word
{
flag = !flag; // first time (odd position) we are not going to reverse!
//swap from startPos to counter - 1
//set start position to -1 and increment counter
int begin = startPosition;
int end;
if(sentenceLength == counter)
{
end = counter;
}
else
end = counter -1;
char tmp;
//Reverse characters
while(end >= begin & flag){ //lets see whether we are going to reverse or not
tmp = sentence[begin];
sentence[begin] = sentence[end];
sentence[end] = tmp;
end--; begin++;
}
startPosition = -1; //flag used to indicate we have no encountered a character of a string
}
else if(sentence[counter] !=' ' && startPosition == -1) //first time you encounter a letter in a word set the start position
{
startPosition = counter;
}
counter++;
}
return sentence;
}
Input
My name is xyz
Output:
My eman is zyx
The following code does this "special reverse" which reverses any other word in the sentence:
public static void main(String[] args) {
String sentence = "My name is xyz";
System.out.println(specialReverse(sentence)); // My eman is zyx
}
private static String specialReverse(String sentence) {
String result = "";
String[] words = sentence.split(" ");
// we'll reverse only every second word according to even/odd index
for (int i = 0; i < words.length; i++) {
if (i % 2 == 1) {
result += " " + reverse(words[i]);
} else {
result += " " + words[i];
}
}
return result;
}
// easiest way to reverse a string in Java in a "one-liner"
private static String reverse(String word) {
return new StringBuilder(word).reverse().toString();
}
Just for completeness here's Java-8 solution:
public static String reverseSentence(String input) {
String[] words = input.split(" ");
return IntStream.range(0, words.length)
.mapToObj( i -> i % 2 == 0 ? words[i] :
new StringBuilder(words[i]).reverse().toString())
.collect(Collectors.joining(" "));
}
reverseSentence("My name is xyz"); // -> My eman is zyx
package com.eg.str;
// Without using StringBuilder
// INPUT: "Java is very cool prog lang"
// OUTPUT: Java si very looc prog gnal
public class StrRev {
public void reverse(String str) {
String[] tokens = str.split(" ");
String result = "";
String k = "";
for(int i=0; i<tokens.length; i++) {
if(i%2 == 0)
System.out.print(" " + tokens[i] + " ");
else
result = tokens[i];
for (int j = result.length()-1; j >= 0; j--) {
k = "" + result.charAt(j);
System.out.print(k);
}
result = "";
}
}
public static void main(String[] args) {
StrRev obj = new StrRev();
obj.reverse("Java is very cool prog lang");
}
}
//reverse second word of sentence in java
public class ReverseSecondWord {
public static void main(String[] args) {
String s="hello how are you?";
String str[]=s.split(" ");
String rev="";
for(int i=0;i<str[1].length();i++)
{
char ch=str[1].charAt(i);
rev=ch+rev;
}
str[1]=rev;
for(int i=0;i<str.length;i++)
{
System.out.print(str[i]+" ");
}
}
}

How to count white spaces in a given argument?

I find it strange why spaceCount doesn't add up when the expression is "12 + 1". I get an output 0 for spaceCount even though it should be 2. Any insight would be appreciated!
public int countSpaces(String expr) {
String tok = expr;
int spaceCount = 0;
String delimiters = "+-*/#! ";
StringTokenizer st = new StringTokenizer(expr, delimiters, true);
while (st.hasMoreTokens()) {
if ((tok = st.nextToken()).equals(" ")) {
spaceCount++;
}
}
return spaceCount; // the expression is: 12 + 1, so this should return 2, but it returns 0;
}
Your code seems to be ok, but if you want to count spaces you can use this :
int count = str.length() - str.replace(" ", "").length();
A tokenizer is overkill (and doesn't really help you) for this problem. Just loop through all the characters and count the spaces:
public int countSpaces( String expr )
{
int count = 0;
for( int i = 0; i < expr.length(); ++i )
{
if( expr.charAt(i) == ' ' )
++count;
}
return count;
}
Another one line solution could be the following which also performs a NULL check to the string.
int spacesCount = str == null ? 0 : str.length() - str.replace(" ", "").length();
Can also use:
String[] strArr = st.split(" ");
if (strArr.length > 1){
int countSpaces = strArr.length - 1;
}
This will find white spaces, including special ones.
You can keep the pattern so you don't need to compile it every time. If just need to search for " ", a loop should do it instead.
Matcher spaces = Pattern.compile("\\s").matcher(argumentString);
int count = 0;
while (spaces.find()) {
count++;
}

Word count algorithm issue

So I am trying to make a word count program where the user can paste text in to get a word count of type text in to get a word count. The typing text in works for the most part but sometimes I get a string index out of range error when I try to go back and replace text. The pasting works but I am having issues with the string index being out of range issue here as well. My logic works like this: a space equals a word, two spaces back to back is minus one word, and the end of the string counts as a word. I am relatively new to Java and I thought this was going to be an easy thing to make, I was wrong! Some help/explanation would be appreciated!
public static int getWordCount(String getInput, int e){
int numberOfWords = 0;
char l1 = 0;
char l2 = 0;
StringBuilder convertInput = new StringBuilder(getInput);
System.out.println(convertInput);
for (int i = 0, i1 = 1; i < getInput.length();i++, i1++){
l2 = convertInput.charAt(i);
if (l2 == ' '){
numberOfWords += 1;
l1 = convertInput.charAt(i1);
}
if (i == getInput.length() - 1){
numberOfWords += 1;
}
if (l2 == ' ' && l1 == ' '){
numberOfWords -= 1;
}
}
return numberOfWords;
} // end of getWordCount method
you can do this easy and quick with:
String phrase = "word1 word2 word3 word4";
String delims = " "; //u can declare more delims here like delims = " ,.{[]}\";
String[] tokens = phrase.split(delims);
tokens.length = number of words in your string

Parse String and Replace Letters Java

At input i have some string : "today snowing know " , here i have 3 words , so i must to parse them is such way : every character i must compare with all other characters , and to sum how many same characters these words have , like exemple for "o" letter will be 2 (from "today" and "snowing") or "w" letter will be 2 (from "know" and "snowing"). After that i must to replace these characters with number(transformed in char format) of letters. The result should be "13111 133211 1332".
What i did ?
First i tape some words and
public void inputStringsForThreads () {
boolean flag;
do {
// will invite to input
stringToParse = Input.value();
try {
flag = true;
// in case that found nothing , space , number and other special character , throws an exception
if (stringToParse.equals("") | stringToParse.startsWith(" ") | stringToParse.matches(".*[0-9].*") | stringToParse.matches(".*[~`!##$%^&*()-+={};:',.<>?/'_].*"))
throw new MyStringException(stringToParse);
else analizeString(stringToParse);
}
catch (MyStringException exception) {
stringToParse = null;
flag = false;
exception.AnalizeException();
}
}
while (!flag);
}
I eliminate spaces between words , and from those words make just one
static void analizeString (String someString) {
// + sign treat many spaces as one
String delimitator = " +";
// words is a String Array
words = someString.split(delimitator);
// temp is a string , will contain a single word
temp = someString.replaceAll("[^a-z^A-Z]","");
System.out.println("=============== Words are : ===============");
for (int i=0;i<words.length;i++)
System.out.println((i+1)+")"+words[i]);
}
So i try to compare for every word in part (every word is split in letters) with all letter from all words , But i don know how to count number of same letter and after replace letters with correct number of each letter??? Any ideas ?
// this will containt characters for every word in part
char[] motot = words[id].toCharArray();
// this will containt all characters from all words
char[] notot = temp.toCharArray();
for (int i =0;i<words[i].length();i++)
for (int j=0;j<temp.length ;j++)
{
if (i == j) {
System.out.println("Same word");
}
else if (motot[i] == notot[j] ) {
System.out.println("Found equal :"+lol[i]+" "+lol1[j]);
}}
For counting you might want to use a Map<Character, Integer> counter like java.util.HashMap. If getting a Value(Integer) using a specific key (Character) from counter is 'not null', then your value++ (leverage autoboxing). Otherwise put a new entry (char, 1) in the counter.
Replacing the letters with the numbers should be fairly easy then.
It is better to use Pattern Matching like this:
initially..
private Matcher matcher;
Pattern regexPattern = Pattern.compile( pattern );
matcher = regexPattern.matcher("");
for multiple patterns to match.
private final String[] patterns = new String [] {/* instantiate patterns here..*/}
private Matcher matchers[];
for ( int i = 0; i < patterns.length; i++) {
Pattern regexPattern = Pattern.compile( pattern[i] );
matchers[i] = regexPattern.matcher("");
}
and then for matching pattern.. you do this..
if(matcher.reset(charBuffer).find() ) {//matching pattern.}
for multiple matcher check.
for ( int i = 0; i < matchers.length; i++ ) if(matchers[i].reset(charBuffer).find() ) {//matching pattern.}
Don't use string matching, not efficient.
Always use CharBuffer instead of String.
Here is some C# code (which is reasonably similar to Java):
void replace(string s){
Dictionary<char, int> counts = new Dictionary<char, int>();
foreach(char c in s){
// skip spaces
if(c == ' ') continue;
// update count for char c
if(!counts.ContainsKey(c)) counts.Add(c, 1);
else counts[c]++;
}
// replace characters in s
for(int i = 0; i < s.Length; i++)
if(s[i] != ' ')
s[i] = counts[s[i]];
}
Pay attention to immutable strings in the second loop. Might want to use a StringBuilder of some sort.
Here is a solution that works for lower case strings only. Horrible horrible code, but I was trying to see how few lines I could write a solution in.
public static String letterCount(String in) {
StringBuilder out = new StringBuilder(in.length() * 2);
int[] count = new int[26];
for (int t = 1; t >= 0; t--)
for (int i = 0; i < in.length(); i++) {
if (in.charAt(i) != ' ') count[in.charAt(i) - 'a'] += t;
out.append((in.charAt(i) != ' ') ? "" + count[in.charAt(i) - 'a'] : " ");
}
return out.substring(in.length());
}

Categories