falcoware, EzKekPolice, если чисто с точки зрения комбинаторики, то это получается сумма размещений с последовательным уменьшением количества элементов слова. Для алфавита с мощностью 3, выглядит так:
где количество размещений
Реализация данного алгоритма на языке C#: Рекурсивные методы:
Код
// Факториал числа n int Factorial(int n) { if (n == 0) return 1;
return Factorial(n - 1) * n; } // Сумма размещений для мощности cap int Comb(int cap, int n) { if (n < 2) return cap;
return Factorial(cap) / Factorial(cap - n) + Comb(cap, n - 1); } // Перегрузка для удобства вызова int Comb(int cap) { return Comb(cap, cap); }
С использованием циклов:
Код
// Факториал числа n int Factorial(int n) { int result = 1; for (int i = n; i > 0; i--) result *= i; return result; } // Сумма размещений для мощности cap int Comb(int cap) { int result = 0;
for (int i = cap; i > 0; i--) result += Factorial(cap) / Factorial(cap - i);
return result; }
Сообщение отредактировал Rean - Четверг, 22 Декабря 2016, 23:54
Вот этот комментарий "тут все комбинации порядковых номеров. от нуля до 3" (точнее, будущий код под ним и что там должно быть?) как влияет на результат sStringResult?
Сообщение отредактировал 8Observer8 - Суббота, 24 Декабря 2016, 16:31
Вот рабочий масштабируемый вариант. Представляет из себя работу с функцией по нахождению всех комбинаций размещения множества n (src) по k элементам.
Код
class Program { static void Main(string[] args) { string source = "abcd"; List<string> result = new List<string>();
for (int i = 0; i < source.Length; i++) Placement(i + 1, source, ref result);
for (int i = 0; i < result.Count; i++) Console.WriteLine("{0}", result[i]);
Console.WriteLine("-------------------------------"); Console.WriteLine("Всего {0} возможных комбинаций.", result.Count);
Console.Read(); }
/// <summary> /// Добавляет в результирущющий список rsl все комбинации слов из elm элементов множества src. /// </summary> /// <param name="k">Количество элементов в слове.</param> /// <param name="src">Исходное множество элементов.</param> /// <param name="rsl">Результирующий список строк.</param> /// <param name="lStr">Строка для хранения данных рекурсии. По умолчанию, пуста.</param> static void Placement (int k, string src, ref List<string> rsl, string lStr = "") { foreach (char ch in src) if (!lStr.Contains(ch)) if (k == 1) rsl.Add(lStr.ToString() + ch.ToString()); else Placement(k - 1, src, ref rsl, lStr + ch.ToString()); }
}
Из минусов: string'и и рекурсия. Зато достаточно компактно. Ссылка на реализацию: Permutation
Сообщение отредактировал Rean - Воскресенье, 25 Декабря 2016, 02:22
falcoware, хорошо, для тройного + двойной + одинарный алфавитов - ваш подход работает. Напишите, пожалуйста, подробнее, как быть со строками произвольной длины.
Вот что сейчас выдаёт программа: abc bc acb cb bac ac bca ca cab ab cba ba a b c
Код
using System; using System.Collections.Generic;
namespace ConsoleApplication1 { class Program { static void Main(string[] args) { char[] arr = { 'a', 'b', 'c' };
List<string> result = getCombinations(arr);
// Show result foreach (var item in result) { Console.WriteLine(item); }
// Delay Console.ReadKey(); }
public static List<string> getCombinations(char[] arr) { List<string> resultList = new List<string>(); string sStringResult1; string sStringResult2;
for (int ix = 0; ix < arr.Length; ix++) { for (int iy = 0; iy < arr.Length; iy++) { for (int iz = 0; iz < arr.Length; iz++) { if (ix == iy) { continue; } if (ix == iz) { continue; } if (iy == iz) { continue; }
foreach (var item in arr) { resultList.Add(item.ToString()); }
return resultList; } } }
Добавлено (24 декабря 2016, 20:13) --------------------------------------------- Rean, отличная работа! Маленькое замечание. У меня VS ругнулся на строку "if (!lStr.Contains(ch))", что не может преобразовать "char" в "string", я добавил преобразование в строку "if (!lStr.Contains(ch.ToString()))"
Сообщение отредактировал 8Observer8 - Суббота, 24 Декабря 2016, 20:14
Маленькое замечание. У меня VS ругнулся на строку "if (!lStr.Contains(ch))", что не может преобразовать "char" в "string", я добавил преобразование в строку "if (!lStr.Contains(ch.ToString()))"
Странно. У меня в VS 2015 есть перегрузка с char. Но можно и через ToString() (думаю, там так и реализовано)
Добавлено (25 декабря 2016, 02:06) --------------------------------------------- Глянул на подключенные пространства: так у меня там Linq, оттуда и перегрузка с char А вот здесь можно рассмотреть/обсудить C++ версию от falcoware. Я сильно не вдавался в подробности, что и как работает. Если у кого будет желания - можете допилить.
Сообщение отредактировал Rean - Суббота, 24 Декабря 2016, 22:39
У меня мелькнула мысль, что до нас эту задачу решали. Выяснил, что у Кнут'а есть 4-й том разбитый на части: Искусство программирования, том 4А. Комбинаторные алгоритмы , часть 1 Искусство программирования, том 4, выпуск 2. Генерация всех кортежей и перестановок Искусство программирования, том 4, выпуск 3. Генерация всех сочетаний и разбиений
Если для автора темы всё ещё актуальна эта проблема, то возможно в книге он найдёт что-то полезное для себя.