Напрашивается вариант представить результирующие строки записями в N-ричной системе счисления, где заданные буквы есть цифры от 0 до N-1, тогда задача сводится к выводу однозначных чисел от 0 до N-1, двузначных от 0 до N²-1, трёхзначных от 0 до N³-1. Запись в N-ричной системе легко получить, используя остаток от деления и деление.
#include <vector>
std::string gen(std::vector<char> alphabet, std::size_t idx, std::size_t digits)
{
std::string ret(digits, alphabet[0]);
std::size_t alphas = alphabet.size();
while (digits--)
{
ret[digits] = alphabet[idx % alphas];
idx /= alphas;
}
return ret;
}
void gen_and_out(std::size_t n, std::vector<char> alphabet)
{
std::size_t numbers = 1;
std::size_t alphas = alphabet.size();
for (std::size_t i = 0; i < n; ++i)
{
numbers *= alphas; // на каждом шаге чисел в alphas раз больше
for (std::size_t cur = 0; cur < numbers; ++cur)
{
std::cout << gen(alphabet, cur, i + 1) << std::endl;
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
gen_and_out(3, std::vector<char>({ 'a', 'b', 'c'}));
}
Второй вариант - это представить эти строки как запись числа в особой системе счисления без нуля - с цифрами от 1 до N. В этом случае легко преобразовать такую запись в число - ∑aᵢ×Nⁱ, а вот обратное преобразование должно учитывать, что у нас нет нуля, тогда если остаток получился равным нулю, цифру нужно взять N.
В отличие от первого варианта, здесь нет отдельных циклов для однозначной, двузначной и трёхзначных записей, так как результаты идут подряд, за "c" следует "aa", за "cc" - "aaa", и так далее.
#include <vector>
std::string gen(std::vector<char> alphabet, std::size_t idx)
{
std::vector<char> ret;
std::size_t alphas = alphabet.size();
while (idx)
{
std::size_t cur = idx % alphas;
if (!cur) // нет нуля
cur = alphas;
ret.push_back(alphabet[cur - 1]);
idx = (idx - cur) / alphas;
}
return std::string(ret.rbegin(), ret.rend());
}
void gen_and_out(std::size_t n, std::vector<char> alphabet)
{
std::size_t numbers = 1;
std::size_t alphas = alphabet.size();
for (std::size_t i = 0; i < n; ++i)
{
numbers *= alphas;
numbers += 1;
}
for (std::size_t i = 1; i < numbers; ++i)
std::cout << gen(alphabet, i) << std::endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
gen_and_out(3, std::vector<char>({ 'a', 'b', 'c' }));
}
На закуску, как та же задача решается на Haskell:
gen alphas n = concatMap (`replicateM` alphas) [1..n]
main = mapM_ putStrLn $ gen "abc" 3