#include <iostream>
#include <string>
#include <unordered_set>
#include <sstream>
/*
Determine whether two sentences talk about similar topics
using a simple, efficient NLP approach in idiomatic C++.
Steps:
1. Normalize text (lowercase + remove punctuation)
2. Tokenize into words
3. Remove stop-words
4. Compute Jaccard similarity between word sets
5. Compare against a threshold
*/
// Normalize a sentence: lowercase + remove punctuation
std::string normalize(const std::string& s) {
std::string out;
out.reserve(s.size());
for (char ch : s) {
if (std::isalnum(static_cast<unsigned char>(ch)) || std::isspace(static_cast<unsigned char>(ch))) {
out.push_back(std::tolower(static_cast<unsigned char>(ch)));
}
// punctuation is skipped
}
return out;
}
// Tokenize into words and remove stop-words
std::unordered_set<std::string> tokenize(const std::string& s) {
static const std::unordered_set<std::string> stop_words{
"the","a","an","and","or","but","is","are","was","were",
"to","of","in","on","for","with","as","by","that"
};
std::unordered_set<std::string> words;
std::stringstream ss(s);
std::string word;
while (ss >> word) {
if (!stop_words.count(word)) {
words.insert(word);
}
}
return words;
}
// Compute Jaccard similarity: |A ∩ B| / |A ∪ B|
double jaccard_similarity(const std::unordered_set<std::string>& A,
const std::unordered_set<std::string>& B) {
size_t intersection = 0;
for (const auto& w : A) {
if (B.count(w)) {
++intersection;
}
}
size_t union_size = A.size() + B.size() - intersection;
return union_size == 0 ? 0.0 : static_cast<double>(intersection) / union_size;
}
// Determine if two sentences discuss similar topics
bool similar_topics(const std::string& s1, const std::string& s2, double threshold = 0.25) {
auto n1 = normalize(s1);
auto n2 = normalize(s2);
auto w1 = tokenize(n1);
auto w2 = tokenize(n2);
double sim = jaccard_similarity(w1, w2);
std::cout << "Similarity score: " << sim << "\n";
return sim >= threshold;
}
int main() {
std::string sentence1 = "Cats are wonderful pets that enjoy playing.";
std::string sentence2 = "Many people keep dogs or cats as household animals.";
std::cout << "Sentence 1: " << sentence1 << "\n";
std::cout << "Sentence 2: " << sentence2 << "\n\n";
bool result = similar_topics(sentence1, sentence2);
std::cout << "Do they talk about similar topics? "
<< (result ? "Yes" : "No") << "\n";
}
/*
run:
Sentence 1: Cats are wonderful pets that enjoy playing.
Sentence 2: Many people keep dogs or cats as household animals.
Similarity score: 0.0909091
Do they talk about similar topics? No
*/