#include #include #include #include #include #include #include #include #include #include #ifdef __cpp_lib_print #include #else namespace std { template inline void print(T format, Args&&... args) { auto f = std::vformat(format, std::make_format_args(args...)); std::cout << f; } template inline void println(T format, Args&&... args) { auto f = std::vformat(format, std::make_format_args(args...)); std::cout << f << std::endl; } } #endif constexpr std::array BAD_WORDS ={ L"recovery", L"techie", L"http", L"https", L"digital", L"hack", L"::", L"//", L"com", L"@", L"crypto", L"bitcoin", L"wallet", L"hacker", L"welcome", L"whatsapp", L"email", L"cryptocurrency", L"stolen", L"freeze", L"quick", L"crucial", L"tracing", L"scammers", L"expers", L"hire", L"century", L"transaction", L"essential", L"managing", L"contact", L"contacting", L"understanding", L"assets", L"funds", }; constexpr auto SHORTEST_BAD_WORD = std::ranges::fold_left(BAD_WORDS, std::numeric_limits::max(), [](std::size_t current, const std::wstring_view &word) { return std::min(current, word.size()); } ); constexpr auto LONGEST_BAD_WORD = std::ranges::fold_left(BAD_WORDS, std::numeric_limits::min(), [](std::size_t current, const std::wstring_view &word) { return std::max(current, word.size()); } ); struct AnalysisResult { std::size_t totalWordCount = 0; std::size_t totalCapitalizedCount = 0; std::size_t totalSentenceCount = 0; std::size_t totalNumberCount = 0; std::size_t totalForbiddenCount = 0; std::size_t fileCount = 1; std::size_t failCount = 0; operator std::string() const { return std::format( "Word Count: {}\nCapitalized Count: {}\nSentence Count: {}\nNumber Count: {}\nForbidden Count: {}\nFile Count: {}\nFail Count: {}", totalWordCount, totalCapitalizedCount, totalSentenceCount, totalNumberCount, totalForbiddenCount, fileCount, failCount ); } friend AnalysisResult operator+(const AnalysisResult &lhs, const AnalysisResult &rhs) { return { lhs.totalWordCount + rhs.totalWordCount, lhs.totalCapitalizedCount + rhs.totalCapitalizedCount, lhs.totalSentenceCount + rhs.totalSentenceCount, lhs.totalNumberCount + rhs.totalNumberCount, lhs.totalForbiddenCount + rhs.totalForbiddenCount, lhs.fileCount + rhs.fileCount, lhs.failCount + rhs.failCount }; }; }; void check_word(std::wstring& word, std::size_t &forbiddenCount) { if (word.size() < SHORTEST_BAD_WORD || word.size() > LONGEST_BAD_WORD) { return; } std::transform(word.begin(), word.end(), word.begin(), ::towlower); if (std::ranges::find_if(BAD_WORDS, [&word](const std::wstring_view &badWord) { // Case-insensitive check if badword is inside word return word.contains(badWord); }) != BAD_WORDS.end()) { forbiddenCount++; } } AnalysisResult parseFile(const std::string_view &filename) { std::wifstream file; file.imbue(std::locale(std::locale(), new std::codecvt_utf8)); file.open(std::string(filename)); // Modified line if (!file.is_open()) { std::println("File doesn't exist: {}", filename); return { }; } AnalysisResult result{ }; bool inWord = false; bool isDigit = false; wchar_t c; std::wstring word; while (file.get(c)) { if (c == '.') { result.totalSentenceCount++; } if (std::isspace(c)) { inWord = false; isDigit = false; if (!word.empty()) { check_word(word, result.totalForbiddenCount); word.clear(); } continue; } else { if (!inWord) { result.totalWordCount++; if (std::isupper(c)) { result.totalCapitalizedCount++; } } inWord = true; if (std::isdigit(c) && !isDigit) { result.totalNumberCount++; isDigit = true; } word.push_back(c); } }; // std::cout << "File state: " << file.rdstate() << " EOF" << file.eof() << " Fail" << file.fail() << " Bad" << file.bad() << std::endl; if (!word.empty()) { check_word(word, result.totalForbiddenCount); } file.close(); if (file.fail() && !file.eof()) { result.failCount++; } return result; } int main(const int argc, char *argv[]) { if (argc < 2) { std::println("Usage: {} ... ", argv[0]); return 1; } const AnalysisResult result = std::transform_reduce(std::execution::par_unseq, std::next(argv), argv + argc, AnalysisResult{ .fileCount = 0 }, std::plus{ }, parseFile ); double capitalizedPercentage = (result.totalWordCount > 0) ? static_cast(result.totalCapitalizedCount) / result.totalWordCount * 100.0 : 0; double forbiddenPercentage = (result.totalWordCount > 0) ? static_cast(result.totalForbiddenCount) / result.totalWordCount * 100.0 : 0; double wordCountPerSentence = (result.totalSentenceCount > 0) ? static_cast(result.totalWordCount) / result.totalSentenceCount : 0; std::println("{}\nCapitalized Percentage: {}%\nForbidden Percentage: {}%\nWord Count Per Sentence: {}", std::string(result), capitalizedPercentage, forbiddenPercentage, wordCountPerSentence ); return 0; }