Распределить слова по группам и сгенерировать текст C++
- Суть программы:
- Пользователь задаёт алфавит языка (вводит несколько букв) и максимальную длину слова (вводит число);
- Программа генерирует все возможные слова из этих букв (не обязательно существующие);
- Все слова рандомно распределяются на 3 группы;
- Пользователь задаёт количество предложений для текста;
- Программа составляет текст из предложений по типу: 1 рандомное слово из 1-ой группы + 1 рандомное слово из 2-ой группы + 1 рандомное слово из 3 группы. (То есть в предложении 3 слова, кол-во предложений задает пользователь);
- Вывести этот текст в отдельный файл.
Не могу сделать нормально 3-5 пункт. Наверное, нужно изначально слова в массив забивать, но не знаю как. Или есть еще какой способ? Подскажите, пожалуйста.
#include <iostream>
#include <stdio.h>
#include <windows.h>
#include <string>
#include <time.h>
using namespace std;
void vocabulary(string s, string h, string* vocab, string* skaz, string* podl, string* dop, int n)
{
string k;
for (size_t i = 0; i < h.length(); i++)
{
if (s.length() == n)
{ break; }
k = h;
vocabulary(s + h[i], h, vocab, skaz, podl, dop, n);
}
*vocab += s + '\n';
int i = rand() % 3;
if (i == 0) {*skaz += s + ' '; }
if (i == 1) {*podl += s + ' '; }
if (i == 2) {*dop += s + ' '; }
}
int main()
{
setlocale(0, "");
srand(time(0));
string alphabet, vocab, skaz, podl, dop, text;
int length, n;
cout << "Задайте алфавит языка:\t";
cin >> alphabet;
cout << "Задайте максимальную длину слова:\t";
cin >> length;
cout << "Словарь языка:\n";
vocabulary("", alphabet, &vocab, &skaz, &podl, &dop, length);
cout << vocab << "---------------------------------\n";
cout << skaz << endl;
cout << podl << endl;
cout << dop << endl;
cout << "Введите количество предложений для текста:\t";
cin >> n;
system("pause");
return 0;
}
Ответы (1 шт):
Вот Вам вариант моего решения:
Алгоритм:
1) Берем строку символов и подготавливаем ее (делаем уникальной и все low и без цифр и пробелов) ну или введите свои символы и отработайте аналогично.
2) Генерируем все комбинации по пример f(ab,2) -> aa ab ba bb и тд. Учтите,что это надо повторить от 1 буквы до макс длинны слова от 1 буквы до максимума чтобы получить все комбинации разной длинны. + данные будут генерироваться без "схожих" (aac caa) которые при пермутации будут давать одинаковые данные.
3) Пермутим строку и прогоняем ее через std::set чтобы все было юникально
4) Далее чпросто рандомно перемешиваем конетйнер всех слов и дробим его на n частей (2 параметр в GenDicts) части
5) генерим те же n чисел числа и готовим новую строку по индексам этих рандомов
ПРОФИТ
Вот код:
#include <string>
#include <iostream>
#include <vector>
#include <set>
#include <random>
#include <algorithm>
#include <functional>
#include <iterator>
std::string PrepareStr(std::string line) {
std::for_each(std::begin(line), std::end(line), [](char& c){ if (std::isupper(c)) {c = std::tolower(c);}});
if (!std::is_sorted(std::begin(line), std::end(line))) {
std::sort(std::begin(line), std::end(line));
}
line.erase(std::unique(std::begin(line), std::end(line)), std::end(line));
line.erase(std::remove_if(std::begin(line), std::end(line), [](char c){ return std::isdigit(c) || std::isspace(c) ; }), std::end(line));
return line;
}
void CombinationRepetitionUtil(std::vector<std::string>& ret, std::vector<int> chosen, std::string& line,
std::size_t index, std::size_t r, int start, int end) {
if (index == r) {
std::string tmp;
for (std::size_t i = 0; i < r; i++) {
tmp += line[static_cast<std::size_t>(chosen.at(i))];
}
ret.push_back(tmp);
return;
}
for (int i = start; i <= end; i++) {
chosen[index] = i;
CombinationRepetitionUtil(ret, chosen, line, index + 1,
r, i, end);
}
return;
}
std::vector<std::string> CombinationRepetition(std::string line, int n, std::size_t r) {
std::vector<int> chosen(static_cast<std::size_t>(r + 1));
std::vector<std::string> ret;
CombinationRepetitionUtil(ret, chosen, line, 0, r, 0, n-1);
return ret;
}
std::vector<std::string> GenAllWorlds(std::vector<std::string> v) {
std::set<std::string> s;
for (auto line : v) {
do {
s.insert(line);
} while (std::next_permutation(std::begin(line), std::end(line)));
}
return {std::begin(s), std::end(s)};
}
uint64_t GenRandUInt(std::size_t low_bound, std::size_t hight_bound) {
static std::random_device r_dev{};
static std::mt19937_64 mt_engine(r_dev());
static std::uniform_int_distribution<> u_int_d(static_cast<int32_t>(low_bound),
static_cast<int32_t>(hight_bound));
static auto PRNG{std::bind(u_int_d, mt_engine)};
return static_cast<uint64_t>(PRNG());
}
std::vector<std::vector<std::string>> GenDicts(std::vector<std::string> m, std::size_t dict_count) {
std::vector<std::vector<std::string>> ret(dict_count);
auto randomer = [](int N){ static std::random_device r_dev{};
std::mt19937_64 generator(r_dev());
std::uniform_int_distribution<> uid(0, N-1);
return uid(generator);};
std::random_shuffle(std::begin(m), std::end(m), randomer);
for (size_t i{0}; i < dict_count; ++i) {
size_t k{m.size() / dict_count};
size_t kk{m.size() % dict_count};
auto b_it = std::begin(m);
if (i != dict_count - 1) {
ret[static_cast<std::size_t>(i)].resize(k);
std::copy(std::begin(m) + i * k,
std::begin(m) + (i + 1) * k,
std::begin(ret[i]));
} else {
ret[static_cast<std::size_t>(i)].resize(k + kk);
std::copy(std::begin(m) + i * k,
std::begin(m) + (i + 1) * k + kk,
std::begin(ret[i]));
}
}
return ret;
}
std::string Genline(std::vector<std::vector<std::string>> v) {
std::string ret;
for (int i{0}; i < v.size(); ++i) {
ret += v[1][GenRandUInt(0, v[1].size() - 1)];
if (i != v.size() - 1) {
ret += " ";
}
}
return ret;
}
int main() {
std::string alphabet{"abc fa324 X h dfah2443d eee"};
alphabet = PrepareStr(alphabet);
std::cout << "line is : " << alphabet << std::endl;
std::size_t lenth_size{2};
std::vector<std::string> mm{};
for (int i = 1; i <= lenth_size; ++i) {
auto comb{CombinationRepetition(alphabet, static_cast<int>(alphabet.length()), i)};
auto m{GenAllWorlds(comb)};
mm.insert(std::end(mm), std::make_move_iterator(std::begin(m)),std::make_move_iterator(std::end(m)));
}
std::cout << "mm size = " << mm.size() << std::endl;
auto three_dict{GenDicts(mm, 4)};
for (const auto cnt : three_dict) {
std::cout << cnt.size() << std::endl;
}
std::cout << Genline(three_dict) << std::endl;
return 0;
}