diff options
Diffstat (limited to 'main.cpp')
| -rw-r--r-- | main.cpp | 270 |
1 files changed, 269 insertions, 1 deletions
@@ -1,6 +1,274 @@ #include <iostream> +#include <StringTools/Stringtools.h> +#include <string> +#include <sstream> +#include <functional> + +constexpr char UPPERCASE = (1<<5); +constexpr char LOWERCASE = 0; + +bool IsUpper(char c) { + return !(c & (1<<5)); +} + +char MakeUpper(char c) { + if (IsUpper(c)) + return c; + else + return c & ~(1<<5); +} + +char MakeLower(char c) { + if (!IsUpper(c)) + return c; + else + return c | (1<<5); +} + +char CopySign(char sign, char c) { + if (IsUpper(sign)) + return MakeUpper(c); + else + return MakeLower(c); +} + +std::string ReplaceButKeepCapitalization( + const std::string& str, + std::string find, + const std::string& sub, + std::function<bool(const std::string&, int)> onlyIf = [](const std::string&, int){return true;} +) { + + // Quick accepts-and rejects + if (str.length() == 0) + return ""; + else if (find.length() == 0) + return str; + + std::stringstream ss; + + // Better safe than sorry + find = StringTools::Lower(find); + + for (std::size_t i = 0; i < str.length(); i++) + { + const std::string foundInText = str.substr(i, find.length()); + const std::string foundInText_lower = StringTools::Lower(foundInText); + if (foundInText_lower == find) + { + // Advance i accordingly + i += foundInText.length()-1; + + // Ask the callback if we should replace this one + if (onlyIf(foundInText, i)) + { + // Here we've found our occurrence... + // We have three possible cases: + // 1: len(find) == len(sub), in this case we want to sync capitalization by index. + // 2: len(find) < len(sub), in this case we sync by index, BUT... + // 2.1: len(sub) - len(find) == 1, ...following characters of sub are lowercase + // 2.1: len(sub) - len(find) > 1, ...following characters of sub are the same case as the following char. + // Take find[-1] instead, if the following char is not a letter + // 3: len(find) > len(sub): sync capitalization by index + + // We want to sync capitalization by index + // This accounts for both cases: 1 and 3 + if (foundInText.length() >= sub.length()) + { + for (std::size_t j = 0; j < sub.length(); j++) + { + const char cf = foundInText[j]; + const char cs = sub[j]; + + ss << CopySign(cf, cs); + } + } + + // in this case we sync by index, BUT... + else if (foundInText.length() < sub.length()) + { + char followingCharsSign = 0; + bool doHaveFollowingChar = false; + // Do we even have a following char? + if (str.length() >= i + foundInText.length() + 1) + { + const char followingChar = str[i + foundInText.length()]; + + // Is it a letter? + if ((followingChar >= 'a' && followingChar <= 'z') || + (followingChar >= 'A' && followingChar <= 'Z')) + { + // Copy its sign + followingCharsSign = followingChar & (1 << 5); + doHaveFollowingChar = true; + } + } + + // ... following characters of sub are lowercase, or the same sign of the following character + if (sub.length() - foundInText.length() == 1) + { + ss << CopySign(foundInText[0], sub[0]); + + for (std::size_t j = 1; j < sub.length(); j++) + { + const char charSignToUse = doHaveFollowingChar ? followingCharsSign : LOWERCASE; + ss << CopySign(charSignToUse, sub[j]); + } + } + + // ...following characters of sub are the same case as the following char. + // Take find[-1] instead, if the following char is not a letter + else if (sub.length() - foundInText.length() > 1) + { + char lastCharCharSign = 0; + + for (std::size_t j = 0; j < sub.length(); j++) + { + const char cs = sub[j]; + + // Do we still have chars of 'find' left? + if (j < foundInText.length()) { + const char cf = foundInText[j]; + lastCharCharSign = cf & (1 << 5); + } + + const char charSignToUse = doHaveFollowingChar ? followingCharsSign : lastCharCharSign; + ss << CopySign(charSignToUse, cs); + } + } + } + } + else + { + // We do not have an occurrence... just insert the char as is + ss << str[i]; + } + } + else + { + // We do not have an occurrence... just insert the char as is + ss << str[i]; + } + } + + return ss.str(); +} + +std::string MakeUwu(std::string boringString) { + // Easy ones first + // none, lol + + // Slightly more complex... Multichar replacements, but we have to keep capitalization... + boringString = ReplaceButKeepCapitalization(boringString, "th", "tw"); + boringString = ReplaceButKeepCapitalization(boringString, "you", "chou"); + boringString = ReplaceButKeepCapitalization(boringString, "ove", "uv"); + boringString = ReplaceButKeepCapitalization(boringString, "up", "uwp"); + + // Replace N with Ny, but only if succeeded by a vowel + boringString = ReplaceButKeepCapitalization( + boringString, + "n", + "ny", + [boringString](const std::string& found, int index) + { + // Don't replace, if we are on the last char + if (index == boringString.length() - 1) + return false; + + // Only replace if the next char is a vowel + const std::string vowels = "euioa"; + const char nextChar = MakeLower(boringString[index + found.length()]); + + // Is this a vowel? + for (const char vowel : vowels) + if (vowel == nextChar) + return true; + + // Else, don't replace + return false; + } + ); + + // Replace R with W, but only if not preceded by a vowel + boringString = ReplaceButKeepCapitalization( + boringString, + "r", + "w", + [boringString](const std::string& found, int index) + { + // Do replace, if we are on the first char + if (index == 0) + return true; + + // Only replace if the last char is not a vowel + const std::string vowels = "euioa"; + const char lastChar = MakeLower(boringString[index - 1]); + + // Is this a vowel? + for (const char vowel : vowels) + if (vowel == lastChar) + return false; + + // Else, replace + return true; + } + ); + + // Replace R with nothing, but only if preceded by a vowel + boringString = ReplaceButKeepCapitalization( + boringString, + "r", + "", + [boringString](const std::string& found, int index) + { + // Do replace, if we are on the first char + if (index == 0) + return true; + + // Only replace if the last char is not a vowel + const std::string vowels = "euioa"; + const char lastChar = MakeLower(boringString[index - 1]); + + // Is this a vowel? + for (const char vowel : vowels) + if (vowel == lastChar) + return true; + + // Else, don't replace + return false; + } + ); + + + // Replace L with W, but only if not followed or preceded by another L + boringString = ReplaceButKeepCapitalization( + boringString, + "l", + "w", + [boringString](const std::string& found, int index) + { + const char lastChar = MakeLower(boringString[index - 1]); + const char nextChar = MakeLower(boringString[index + found.length()]); + + return (lastChar != 'l') && (nextChar != 'l'); + } + ); + + + // Also replace some ascii-"emojis' + boringString = StringTools::Replace(boringString, ":)", "UwU :D"); + boringString = StringTools::Replace(boringString, ":-)", "UwwwU :D"); + boringString = StringTools::Replace(boringString, "lol", "XDD"); + boringString = StringTools::Replace(boringString, "^^", "^.^ UwU"); + + return boringString; +} int main() { - std::cout << "Hello, World!" << std::endl; + + std::string buf; + while (std::getline(std::cin, buf)) + std::cout << MakeUwu(buf) << std::endl; + return 0; } |
