Given a string s representing a text, count the number of sentences and words in it.
- A sentence is a sequence of space-separated tokens ending with one or more of ., !, or ?. If the text does not end with a sentence-ending punctuation mark, the last sequence of tokens is also considered a sentence.
- A word is a maximal sequence of alphabetic characters (a-z or A-Z).
Return an array [sentenceCount, wordCount].
Examples:
Input: s = "Sentences"
Output: [1, 1]
Explanation: There is one sentence and one word in the given text.Input: s = "many??? Sentences are"
Output: [2, 3]
Explanation: The text contains two sentences: "many???", "Sentences are". The words are: "many", "Sentences", "are". Hence, the answer is [2, 3].
[Expected Approach] Using Single Traversal - O(|s|) Time and O(1) Space
The idea is to scan the text once and maintain two states: whether we are inside a word and whether we are inside a sentence.
Whenever an alphabetic character starts after a non-word position, we count a new word. Whenever a non-space and non-punctuation character starts after a sentence break, we count a new sentence. If ., !, or ? appears, the current sentence ends.
Let us understand with example:
Input: s = "many??? Sentences are"
- many starts a word and a sentence.
- ? ends the sentence.
- Extra ? do not add new words.
- Sentences starts another sentence and word.
- are starts another word.
So, sentences = 2 and words = 3.
#include <iostream>
#include <vector>
#include <cctype>
using namespace std;
vector<int> sentenceWord(string& s) {
int sentenceCount = 0;
int wordCount = 0;
bool inSentence = false;
bool inWord = false;
for (char ch : s) {
if (ch == '.' || ch == '!' || ch == '?') {
inSentence = false;
inWord = false;
} else if (ch == ' ') {
inWord = false;
} else {
// Start of a new word.
if (!inWord && isalpha(ch)) {
inWord = true;
wordCount++;
}
// Start of a new sentence.
if (!inSentence) {
inSentence = true;
sentenceCount++;
}
}
}
return {sentenceCount, wordCount};
}
void printVector(vector<int>& res) {
cout << "[" << res[0] << ", " << res[1] << "]" << endl;
}
int main() {
string s = "Sentences";
vector<int> res = sentenceWord(s);
printVector(res);
s = "many??? Sentences are";
res = sentenceWord(s);
printVector(res);
return 0;
}
import java.util.ArrayList;
public class GFG {
static ArrayList<Integer> sentenceWord(String s) {
int sentenceCount = 0;
int wordCount = 0;
boolean inSentence = false;
boolean inWord = false;
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
if (ch == '.' || ch == '!' || ch == '?') {
inSentence = false;
inWord = false;
} else if (ch == ' ') {
inWord = false;
} else {
// Start of a new word.
if (!inWord && Character.isLetter(ch)) {
inWord = true;
wordCount++;
}
// Start of a new sentence.
if (!inSentence) {
inSentence = true;
sentenceCount++;
}
}
}
ArrayList<Integer> res = new ArrayList<>();
res.add(sentenceCount);
res.add(wordCount);
return res;
}
public static void main(String[] args) {
String s = "Sentences";
System.out.println(sentenceWord(s));
s = "many??? Sentences are";
System.out.println(sentenceWord(s));
}
}
def sentenceWord(s):
sentenceCount = 0
wordCount = 0
inSentence = False
inWord = False
for ch in s:
if ch == '.' or ch == '!' or ch == '?':
inSentence = False
inWord = False
elif ch == ' ':
inWord = False
else:
# Start of a new word.
if not inWord and ch.isalpha():
inWord = True
wordCount += 1
# Start of a new sentence.
if not inSentence:
inSentence = True
sentenceCount += 1
return [sentenceCount, wordCount]
if __name__ == "__main__":
s = "Sentences"
print(sentenceWord(s))
s = "many??? Sentences are"
print(sentenceWord(s))
using System;
using System.Collections.Generic;
public class GFG
{
static List<int> sentenceWord(string s)
{
int sentenceCount = 0;
int wordCount = 0;
bool inSentence = false;
bool inWord = false;
foreach (char ch in s)
{
if (ch == '.' || ch == '!' || ch == '?')
{
inSentence = false;
inWord = false;
}
else if (ch == ' ')
{
inWord = false;
}
else
{
// Start of a new word.
if (!inWord && char.IsLetter(ch))
{
inWord = true;
wordCount++;
}
// Start of a new sentence.
if (!inSentence)
{
inSentence = true;
sentenceCount++;
}
}
}
return new List<int> { sentenceCount, wordCount };
}
public static void Main()
{
string s = "Sentences";
List<int> res = sentenceWord(s);
Console.WriteLine("[" + string.Join(", ", res) + "]");
s = "many??? Sentences are";
res = sentenceWord(s);
Console.WriteLine("[" + string.Join(", ", res) + "]");
}
}
/**
* @param {string} s
* @returns {number[]}
*/
function sentenceWord(s) {
let sentenceCount = 0;
let wordCount = 0;
let inSentence = false;
let inWord = false;
for (const ch of s) {
if (ch === '.' || ch === '!' || ch === '?') {
inSentence = false;
inWord = false;
} else if (ch === ' ') {
inWord = false;
} else {
// Start of a new word.
if (!inWord && /[a-zA-Z]/.test(ch)) {
inWord = true;
wordCount++;
}
// Start of a new sentence.
if (!inSentence) {
inSentence = true;
sentenceCount++;
}
}
}
return [sentenceCount, wordCount];
}
// Driver Code
let s = "Sentences";
let res = sentenceWord(s);
console.log("[" + res.join(", ") + "]");
s = "many??? Sentences are";
res = sentenceWord(s);
console.log("[" + res.join(", ") + "]");
Output
[1, 1] [2, 3]