Hej, pamiętam jak kiedyś nie potrafiłem poradzić sobie z podobnym zadaniem. Jest na to sprytna sztuczka, na początku nie bierzesz żadnego elementu [0,0,0,0]
potem bierzesz tylko pierwszy [0,0,0,1]
potem drugi [0,0,1,0]
potem tylko drugi i pierwszy[0,0,1,1]
itd. Tak się akuratnie składa że dokładnie w ten sposób są zapisane liczby całkowite w systemie binarnym. Zero to 0000
jeden to 0001
, dwa to 0010
itd. Wszytko co musisz zrobić to przeliterować od zera do liczby możliwych kombinacji (`2^4), i wybrać elementy których pozycje odpowiadają pozycja bitów ustawionych na 1 dla danej iteracji.
class Program
{
static void Main(string[] args)
{
foreach (var set in GetSubSets(new[] { 1, 2, 3, 4 }))
{
Console.WriteLine(SetToString(set));
}
Console.ReadKey();
}
private static string SetToString<T>(T[] set) //T to dowolny typ
{
return "{" + string.Join("; ", set) + "}";
}
public static IEnumerable<T[]> GetSubSets<T>(T[] source) //T to dowolny typ
{
if (source.Length > 32)// int ma 32 bity
throw new IndexOutOfRangeException("Source lenght must be smaller than 32");
int subSetCount = (int)Math.Pow(2, source.Length);
int elementsCount = source.Length;
for (int setOrderNo = 0; setOrderNo < subSetCount; setOrderNo++)
{
List<T> subSet = new List<T>(); // tym czasowo przechowuje set
for (int i = 0; i < elementsCount; i++)
{
if(((setOrderNo>>i)&1)!=0) // sprawdza czy bit na pozycji i ==1
// >> przesuwa liczbe o i pozycji w lewo b100>>3 == 001
// & tworzy nową liczbe z dwóch tak ze na pozycjach gdzie chociaż jedna ma zero po połączeniu będzie zero 00101 & 01011 ==0001
{
subSet.Add(source[i]);
}
}
yield return subSet.ToArray(); //zwraca tablice zaraz po jej utworzeniu
}
}
}