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);
}
}
}