using System; using System.Collections.Generic; using System.Linq; using System.Text; using ExtensionMethods; namespace CryptanalysisCore { public static class Combinatorics { /// /// Vrací permutaci všech prvků seznamu /// Nekontrolují se nijak duplicity /// /// /// Jakákoliv množina prvků /// Seznam permutací public static List> Permutation(List set) { if (set.Count == 1) return new List>() { set }; List> result = new List>(); foreach (List l in Permutation(set.Rest())) result.AddRange(l.Insert(set[0])); return result; } /// /// Vloží prvek na všechny pozice seznamu /// /// /// /// Prvek, který chceme vložit do seznamu /// Seznam seznamů s vloženým prvkem private static List> Insert(this List set, T item) { List> newSet = new List>(); for (int i = 0; i < set.Count + 1; i++) { newSet.Add(new List(set)); newSet[i].Insert(i, item); } return newSet; } /// /// Vrátí variace k-tého řádu z daného seznamu prvků /// /// /// Libovolná množina prvků /// Kolikati prvkové mají být jednotlivé variace /// Seznam variací public static List> Variations(List set, int k) { if (set.Count == k) return Permutation(set); List> variations = new List>(); List var; string binary = new string('0', set.Count); while (binary.Count(x => x == '1') < set.Count) { binary = BinaryAdd(binary); if (binary.Count(x => x == '1') == k) { var = new List(); for (int i = 0; i < set.Count; i++) { if (binary[i] == '1') var.Add(set[i]); } variations.Add(var); } } return variations; } /// /// Vrátí seznam variací s opakováním /// /// /// /// Kolikati prvkové mají být jednotlivé variace /// Seznam variací public static List> VariationsWithRepetition(List set, int k) { List> list = new List>(); List var; if (k == 0) { list.Add(new List()); } else { List> l = VariationsWithRepetition(set, k - 1); foreach (T c in set) { foreach (List s in l) { var = new List() { c }; var.AddRange(s); list.Add(var); } } } return list; } /// /// Přičte k binárnímu číslu jedničku /// /// Řetězec reprezentující binární číslo /// Binární číslo zvýšené o jedničku private static string BinaryAdd(string s) { char[] binary = s.ToCharArray(); for (int i = s.Length - 1; i >= 0; i--) { if (binary[i] == '1') binary[i] = '0'; else { binary[i] = '1'; break; } } return new string(binary); } } }