← index
cplusplus2x.Examples/C++23/wordsplit/shuffle/uniq/main_shuffle.cpp
Source: cplusplus2x.Examples/C++23/wordsplit/shuffle/uniq/main_shuffle.cpp
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <fstream>
#include <iostream>
#include <print>
#include <random>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>

std::string reverse_string(const std::string &);
std::string shuffle_string(const std::string &);

template <typename T>
void echo_words(T &m) {
    for (auto &i : m) {
        std::print("{} ", shuffle_string(i));
    }
    std::print("\n");
}

std::string reverse_string(const std::string &text) {
    std::string data;
    for (int i = text.length() - 1; i >= 0; --i) {
        data += text[i];
    }
    return data;
}

std::string shuffle_string(const std::string &text) {
    static std::random_device rd;
    static std::mt19937 gen(rd());
    std::string data;
    auto is_palindrome = [](const std::string &text) { return text == reverse_string(text); };
    if (text.length() >= 4) {
        char first, last;
        first = text[0];
        last = text[text.length() - 1];
        std::vector<char> ch;
        std::string sub_p;
        for (size_t i = 1; i < text.length() - 1; ++i) {
            sub_p += text[i];
            ch.push_back(text[i]);
        }
        std::string sub_a;
        int attempts = 0;
        bool is_pal = is_palindrome(text);
        bool valid = false;
        do {
            std::shuffle(ch.begin(), ch.end(), gen);
            sub_a = "";
            for (size_t i = 0; i < ch.size(); ++i) {
                sub_a += ch[i];
            }
            ++attempts;
            valid = (sub_p != sub_a);
            if (sub_p.length() <= 2 && is_palindrome(sub_p)) {
                valid = true;
            } else {
                if (valid && !is_pal && ch.size() > 2) {
                    valid = (reverse_string(sub_p) != sub_a);
                }
            }
            if (attempts >= 1000) {
                sub_a = sub_p;
                break;
            }
        } while (!valid);
        data += first;
        data += sub_a;
        data += last;
    } else {
        data = text;
    }
    return data;
}

int main(int argc, char **argv) {

    if (argc != 2) {
        std::println("invalid args.");
        return EXIT_FAILURE;
    }

    std::fstream file;
    file.open(argv[1], std::ios::in);
    if (!file.is_open()) {
        std::println("Error: file not found/could not open: {}", argv[1]);
        return EXIT_FAILURE;
    }
    std::ostringstream stream;
    stream << file.rdbuf();
    std::unordered_set<std::string> words;
    size_t i = 0;
    std::string s = stream.str();
    std::string word;
    size_t index = 0;

    while (i < s.length()) {
        if ((s[i] >= 'a' && s[i] && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z')) {
            word += s[i];
            ++i;
            continue;
        } else {
            ++i;
            if (!word.empty())
                words.insert(word);
            word = "";
            continue;
        }
        ++i;
    }
    std::vector<std::string> shuffled;
    shuffled.resize(words.size());
    std::copy(words.begin(), words.end(), shuffled.begin());
    static std::random_device rd;
    static std::mt19937 gen(rd());
    std::shuffle(shuffled.begin(), shuffled.end(), gen);
    echo_words(shuffled);
    return 0;
}