How could I iterate through each combination of two elements in a HashSet once?
foreach (var elt1 in hashSet) {
foreach (var elt2 in hashSet) {
...
}
}
This would iterate the combinations of two but would iterate each combination TWICE. I'd like to do it once.
I think it's easy to do in Python. Is there any way to do it in C#?
Sample:
input hashSet: { 1, 2, 3, 4 }
iterate through: (1,2), (1,3), (1,4), (2,3), (2,4), (3,4)
There is no built-in method to do this in C#. Since HashSet<T> is not indexed *, you cannot do it with two loops either.
If this is a one-time deal, the simplest solution is to make two nested loops on the results of ToList() or ToArray(), like this:
var items = hashSet.ToList();
for (var i = 0 ; i != items.Count ; i++) {
var a = items[i];
for (var j = i+1 ; j != items.Count ; j++) {
var b = items[i];
}
}
If you are looking for something reusable, make an extension method on IEnumerable<T> that produces all pairs:
static IEnumerable<Tuple<T,T>> MakeAllPairs<T>(this IEnumerable<T> data) {
var items = data.ToList();
for (var i = 0 ; i != items.Count ; i++) {
var a = items[i];
for (var j = i+1 ; j != items.Count ; j++) {
var b = items[i];
yield return Tuple.Create(a, b);
}
}
}
Now you can iterate your pairs in a single loop:
foreach (var pair in hashSet.MakeAllPairs()) {
Console.WriteLine("{0} {1}", pair.Item1, pair.Item2);
}
* Technically, you could use ElementAt<T>(int) extension from Enumerable, but that would be very slow on large sets.
I misread the question originally. This is a new answer
This is what you want (if working index-based is an option). Explanation is below
string[] myArray = GetArray();
for (int i = 0; i < myArray.Length - 1; i++)
{
var element1 = myArray[i];
for(int j = i + 1; j < myArray.Length; j++)
{
var element2 = myArray[j];
Console.WriteLine("{0} {1}", element1, element2);
}
}
Explanation: Assume the following array:
Apple, Banana, Coconut, Zucchini
When i = 0 (Apple), j will be 1 (Banana), then 2 (Coconut), then 3 (Zucchini)
When i = 1 (Banana), j will be 2 (Coconut), then 3 (Zucchini).
And so on...
Basically, you are making sure element j is always ahead of element i. This means you've effectively removed half of the possibilities (where j would be before i), which is what you wanted.
Note: if you want to use sets of equal elements (Apple + Apple), the second for loop needs to change to:
for(int j = i; j < myArray.Length; j++) //notice j = i instead of i + 1
You can work with indexes directly on the HashSet.
Try this:
int int1, int2;
HashSet<int> hs = new HashSet<int>();
hs.Add(1);
hs.Add(2);
hs.Add(3);
for (int i = 0; i < hs.Count-1; i++) {
int1 = hs.ElementAt<int>(i);
for (int j = i + 1; j < hs.Count; j++)
{
int2 = hs.ElementAt<int>(j);
}
}
To return all permutations (viz (1,2) and (2,1)), you can cross join the set with itself using SelectMany:
var hashSet = new HashSet<int>{1,2,3,4,5,6,7,8};
foreach (var elt in hashSet.SelectMany(
x => hashSet.Select(y => new Tuple<int, int>(x, y))))
{
Debug.WriteLine("{0}-{1}", elt.Item1, elt.Item2);
}
Edit: If you just want the unique combinations (viz (1,2) but not (2,1)) then just add a filter only larger values during the cross join:
var hashSet = new HashSet<int> { 1, 2, 3, 4, 5, 6, 7, 8 };
foreach (var elt in hashSet.SelectMany(
x => hashSet.Where(y => y >= x)
.Select(y => new Tuple<int, int>(x, y))))
{
Debug.WriteLine("{0}-{1}", elt.Item1, elt.Item2);
}
Related
Suppose you have one million consecutive integer numbers.
Return all possible values of a,b and c such that
a+b+c<=d.
d will be provided to you.
ex: if the numbers are 1,2,3,4,5,6,7
and d=7
[1,2,3]
[1,2,4]
[1,2,3] will be same as [1,3,2] and [3,2,1]...
Because one million is too big, in the example I adopted 1000 as an example. Also for the convenience, I used 1 to 1000 as the data set.
Suppose
`a<b<c`
Thus 3*a<1000==> a<333.33, so I extract a from 1 to 333.
static void Main(string[] args)
{
int d = 519;
var setA = Enumerable.Range(1, 333);
IEnumerable<int> value = Enumerable.Range(1, 1000);
var result = (from a in setA
from b in value
from c in value
where a!=b && a!=c && b!=c && a + b + c <= d
select new {a,b,c}).ToList().Distinct().ToList();
foreach (var item in result)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
It is slow and throw an System.OutOfMemoryException exception.....
Narrowing down a to 1...333 is a good idea. You can further improve your code though by using the fact that a < b < c, so b,c in Enumerable.Range(1, 1000) is suboptimal.
You can define lower bounds and upper bounds for b and c depending on the given numbers a and b respectively:
a < b => b >= a + 1, b in Enumerable.Range(a + 1, ...)
b < c => c must be in Enumerable.Range(b + 1, ...)
Furthermore you can define bounds for a and b like that:
Since b >= a + 1 and a + b + c <= total, a + (a + 1) + ((a + 1) + 1) <= total must hold true also. That is, a < total / 3 is not sufficient. It is a <= (total - 3) / 3
Similarly a + b + (b + 1) <= total, that is, b <= (total - a - 1) / 2
And of course, a + b + c <= total translates to c <= total - a - b
You can make use of that by nesting the iterations and using SelectMany to flatten the result list:
var result = Enumerable.Range(1, (total - dba - dca) / 3)
.SelectMany(
a => Enumerable.Range(a + 1, (total - a - dcb) / 2 - a)
.SelectMany(
b => Enumerable.Range(b + 1, (total - a - b) - b)
.Select(c => new { a, b, c })));
As for your performance and out-of-memory issue:
Remove the ToList() from your LINQ query. It causes all results to be loaded into memory before you start processing them. Since you only want to print out the tuples, you don't need to load all of them into memory. This is the big strengh of LINQ - it just returns an enumerator without actually calculating the result. If you remove the ToList() from the LINQ query, the for-each loop will calculate one result per iteration, print it out, and forget it again.
As an explanatory answer to your comments:
The implementation of Enumerable.Range looks like this:
private static IEnumerable<int> RangeIterator(int start, int count)
{
for (int i = 0; i < count; ++i)
yield return start + i;
}
Implementation of SelectMany:
private static IEnumerable<TResult> SelectManyIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
{
foreach (TSource source1 in source)
{
foreach (TResult result in selector(source1))
yield return result;
}
}
So for example,
foreach (var item in Enumerable.Range(1, 10).SelectMany(n => Enumerable.Range(1, n)))
{ /* do something */ }
conceptually translates to:
for (int i = 0; i < 10; ++i)
{
var n = 1 + i;
for (int j = 0; j < n; ++j)
{
var result = 1 + j;
/* do something */ // <- processes the current result and forgets it again
}
}
However, when you add ToList:
foreach (var item in Enumerable.Range(1, 10).SelectMany(n => Enumerable.Range(1, n)).ToList())
{ /* do something */ }
this translates to:
var list = new List<int>();
for (int i = 0; i < 10; ++i)
{
var n = 1 + i;
for (int j = 0; j < n; ++j)
{
var item = 1 + j;
list.Add(item); // <- puts the current result in a list
}
}
// list content: 1, 1, 2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6...
foreach (var item in list)
{ /* do something */ }
You can play with the index and your selection for each of the for loops, assuming the input is sorted. The first one should be one third of the main array, second loop should be not more than half but starting from the index of the first loop. something like this:
const int totalElements = 1000;
const int target = 1000;
var value = Enumerable.Range(1, totalElements).OrderBy(dd => dd).ToList();
var sw = new Stopwatch();
var result = new List<int[]>();
sw.Start();
for (int i = 0; i < value.Count / 3; i++)
{
var a = value[i];
for (int j = i + 1; j < value.Count / 2; j++)
{
var b = value[j];
for (int k = j + 1; k < value.Count; k++)
{
var c = value[k];
if (a + b + c <= target)
{
var newR = new[] { a, b, c };
result.Add(newR);
}
}
}
}
sw.Stop();
Console.WriteLine("Time Taken: " + sw.Elapsed.TotalSeconds);
Console.WriteLine("Total result count: " + result2.Count);
For 1000 it's taking 4.9 seconds on my lousy machine, where as the LINQ is throwing outofmemory exception. On top of that you have to add some sort of equality comparison in the LINQ otherwise you'll get results like 1+2+3 and 3+2+1, and using the index only you get rid of that.
You can also adjust the range by doing something like this:
for (int i = 0; i < value.Count / 3; i++)
{
var a = value[i];
var index = value.IndexOf(target - a) + 1;
for (int j = i + 1; j < index; j++)
{
var b = value[j];
var remainingIndex = value.IndexOf(target - (a + b)) + 1;
for (int k = j + 1; k < remainingIndex; k++)
{
var c = value[k];
if (a + b + c <= target)
{
var newR = new[] { a, b, c };
result.Add(newR);
}
}
}
}
It might be better if the values are sequential like this example and you can find the index easily. If that's not the case you have to find the index by Binary Search but it'll probably be similar performance anyway.
I suggest to store the numbers in a SortedSet Class. You can the do the following (pseudocode):
For each n in GetViewBetween (1, d)
For each m in GetViewBetween (n+1, d-n)
For each k in GetViewBetween (m+1, d-n-m)
Store or print or callback or return with continuation the Tuple object with n, m, k
Loop
Loop
Loop
I would suggest you a geometry representation: Imagine, that your 'd' is sum of triangle borders. Thuse, you need to find all triangles that fit. In your code you double variants: (a+b+c) = (b+c+a), for example. But if you make 3 loops for each triangle side, then it would be faster.
Following are two pieces of code I used to compute power sets of elements in a list
code 1)
public static List<List<int>> getCpower(List<int> list)
{
var result = new List<List<int>>();
for (int i = 0; i < (1 << list.Count); i++)
{
var sublist = new List<int>();
for (int j = 0; j < list.Count; j++)
{ if ((i & (1 << j)) != 0)
{ sublist.Add(list[j]);
}
}
result.Add(sublist);
}
return result;
}
code 2)
public static List<List<int>> getCpower(List<int> list)
{
var result = new List<List<int>>();var sublist = new List<int>();
for (int i = 0; i < (1 << list.Count); i++)
{
sublist.Clear();sublist.TrimExcess();
for (int j = 0; j < list.Count; j++)
{ if ((i & (1 << j)) != 0)
{ sublist.Add(list[j]);
}
}
result.Add(sublist);
}
return result;
}
The first code used a new statement and if i try to find out powersets of list with count 30 then OutOfMemoryException arises.So to save memory i used Clear() and TrimExcess() to get the list as if it were initialized using a new statement in code2. But these two codes return different results. I do not get why is this happening. Please help.
Are the two following two pieces not doing the same thing
for(....)
{
var sublist = new List<int>();
for(......)
{
//some code
}
}
and
var sublist = new List<int>();
for(.....)
{
sublist.Clear();sublist.TrimExcess();
for(.... )
{
//some code
}
}
In your second code, you only have a single nested list - you're adding several references referring to the same sublist, which is pointless.
Have you considered that maybe the reason you're running out of space with your first code is because you're fundamentally trying to hold too much data in memory at a time?
You could consider returning an IEnumerable<List<int>> like this:
public static IEnumerable<List<int>> getCpower(List<int> list)
{
for (int i = 0; i < (1 << list.Count); i++)
{
var sublist = new List<int>();
for (int j = 0; j < list.Count; j++)
{ if ((i & (1 << j)) != 0)
{
sublist.Add(list[j]);
}
}
yield return sublist;
}
}
This will now be lazily evaluated - so you could iterate over the top-level sequence, but unless the lists are retained by the caller, you'll only have a single list in memory at a time.
In the second piece of code you are clearing the list of results. This alters the outcome of your algorithm. You are throwing away your results because you are reusing the same list instance for all iterations.
In the second code example, you only ever have a single sublist instance. That same instance is cleared and added to the list again every time you loop through. Here's an example to help you understand:
var sublist = new List<int> { 1, 2, 3 };
var result = new List<List<int>> { sublist };
//result[0] is now {1, 2, 3}
sublist.Clear();
//result[0] is now {}
result.Add(sublist);
//result[0], result[1], and sublist are the same instance
My problem is like this:
I have several lists need to be permuted, but the list numbers are unknowable. And every element numbers in every list are also unknowable. Sicne I would like to traverse all list element combination, like 1) pick A from list 1, A from list 2, A from list 3; 2) ick A from list 1, A from list 2, B from list 3 ... for ALL permutation.
I use nested for-loop to traverse, like if I have two lists, then:
for (int i = 0; i < list[0].EnergyParameters.ListEnergyLevelCandidates.Count; i++)
{
for (int j = 0; j < list[1].EnergyParameters.ListEnergyLevelCandidates.Count; j++)
{
// Do sth
}
}
If I have three lists, then:
for (int i = 0; i < list[0].EnergyParameters.ListEnergyLevelCandidates.Count; i++)
{
for (int j = 0; j < list[1].EnergyParameters.ListEnergyLevelCandidates.Count; j++)
{
for (int k = 0; k < list[2].EnergyParameters.ListEnergyLevelCandidates.Count; k++)
{
// Do sth
}
}
}
Because the list numbers are unknowable, so the nest numbers are unknowable, which means, I don't know how many levels of for-loop needs to be written.
Under this kind of circumstance, how can I write code for dynamic for-loop levels? I don't want to write 10 loops for 10 lists.
In case you do not know how many lists there are, you do not write nested loops: instead, you write recursion. At each level of the invocation you loop a single list, like this:
void AllCombos(List<string>[] lists, int level, string[] current) {
if (level == lists.Length) {
// Do somthing; items of current[] contain elements of the combination
} else {
foreach (var s in lists[level]) {
current[level] = s;
AllCombos(lists, level+1, current);
}
}
}
Call AllCombos as follows:
var lists = new List<string>[10];
for (int i = 0 ; i != 10 ; i++) {
lists[i] = PopulateMyList(i);
}
string[] current = new string[lists.Length];
AllCombos(lists, 0, current);
Let's we have some integer short sorted arrays and we need to find intersection equal or more then predefined constant.
Here is code and it demonstrates what i want to do better then i can explain it in words.
The problem is SPEED. My code is working very slow. It takes about 15 sec on 2000 elements array(on my slow machine). Ofcourse i can implement my own intersection method and parallize code but it give a very limited improvement. Execution time growing as N^2 or something and already for 500k arrays it takes a very very long time. So how can i rewrite algorithm for better perfomance? I am not limited c# language maybe CPU or GPU has good special instructions for such job.
Example:
Input:
1,3,7,8
2,3,8,10
3,10,11,12,13,14
minSupport = 1
Output:
1 and 2: 2, 8
1 and 3: 3
2 and 3: 3, 10
var minSupport = 2;
var random = new Random(DateTime.Now.Millisecond);
// Numbers is each array are unique
var sortedArrays = Enumerable.Range(0,2000)
.Select(x => Enumerable.Range(0,30).Select(t => random.Next(1000)).Distinct()
.ToList()).ToList();
var result = new List<int[]>();
var resultIntersection = new List<List<int>>();
foreach (var array in sortedArrays)
{
array.Sort();
}
var sw = Stopwatch.StartNew();
//****MAIN PART*****//
for (int i = 0; i < sortedArrays.Count-1; i++)
{
for (int j = i+1; j < sortedArrays.Count; j++)
{
var intersect = sortedArrays[i].Intersect(sortedArrays[j]).ToList();
if(intersect.Count()>=minSupport)
{
result.Add( new []{i,j});
resultIntersection.Add(intersect);
}
}
}
//*****************//
sw.Stop();
Console.WriteLine(sw.Elapsed);
EDIT:
Now it takes about 9 sec vs 15 sec with old algorithm on 2000 elements. Well...ofcourse it is not fast enough.
//****MAIN PART*****//
// This number(max value which array can contains) is known
var maxValue = 1000;
var reverseIndexDict = new Dictionary<int,List<int>>();
for (int i = 0; i < maxValue; i++)
{
reverseIndexDict[i] = new List<int>();
}
for (int i = 0; i < sortedArrays.Count; i++)
{
for (int j = 0; j < sortedArrays[i].Count; j++)
{
reverseIndexDict[sortedArrays[i][j]].Add(i);
}
}
var tempArr = new List<int>();
for (int i = 0; i < sortedArrays.Count; i++)
{
tempArr.Clear();
for (int j = 0; j < sortedArrays[i].Count; j++)
{
tempArr.AddRange(reverseIndexDict[j]);
}
result.AddRange(tempArr.GroupBy(x => x).Where(x => x.Count()>=minSupport).Select(x => new[]{i,x.Key}).ToList());
}
result = result.Where(x => x[0]!=x[1]).ToList();
for (int i = 0; i < result.Count; i++)
{
resultIntersection.Add(sortedArrays[result[i][0]].Intersect(sortedArrays[result[i][1]]).ToList());
}
//*****************//
EDIT:
Some improvent.
//****MAIN PART*****//
// This number(max value which array can contains) is known
var maxValue = 1000;
var reverseIndexDict = new List<int>[maxValue];
for (int i = 0; i < maxValue; i++)
{
reverseIndexDict[i] = new List<int>();
}
for (int i = 0; i < sortedArrays.Count; i++)
{
for (int j = 0; j < sortedArrays[i].Count; j++)
{
reverseIndexDict[sortedArrays[i][j]].Add(i);
}
}
for (int i = 0; i < sortedArrays.Count; i++)
{
var tempArr = new Dictionary<int, List<int>>();
for (int j = 0; j < sortedArrays[i].Count; j++)
{
var sortedArraysij = sortedArrays[i][j];
for (int k = 0; k < reverseIndexDict[sortedArraysij].Count; k++)
{
if(!tempArr.ContainsKey(reverseIndexDict[sortedArraysij][k]))
{
tempArr[reverseIndexDict[sortedArraysij][k]] = new[]{sortedArraysij}.ToList();
}
else
{
tempArr[reverseIndexDict[sortedArraysij][k]].Add(sortedArrays[i][j]);
}
}
}
for (int j = 0; j < reverseIndexDict.Length; j++)
{
if(reverseIndexDict[j].Count>=minSupport)
{
result.Add(new[]{i,j});
resultIntersection.Add(reverseIndexDict[j]);
}
}
}
// and here we are filtering collections
//*****************//
There are two solutions:
Let us suppose you have 3 sorted arrays and you have to find the intersection between them. Traverse the first array and run a binary search on the rest of the two arrays for the element in first array. If the respective binary search on two list gave positive, then increment the counter of intersection.
result = List
for element in Array1:
status1 = binarySearch(element, Array2)
status2 = binarySearch(element, Array2)
status = status & status
if status == True:
count++
if count == MAX_INTERSECTION:
result.append(element)
break
Time Complexity : N * M * Log(N),
where,
N = Number of element in the array
M = Number of arrays
This solution works only if the number in the arrays are positive integers. Calculate the maximum and the minimum number out of the total elements in all the sorted arrays. As it is sorted, we can determine it by surveying the start and end element of the sorted arrays given. Let the greatest number be max and the lowest number be min. Create an array of size max - min and fill it with zero. Let us suppose you have 3 Arrays, now start traversing the first array and and go to the respective index and increment the value in the previously created array. As mentioned below:
element is 5 in Array 1, the New_array[5]+=1
Traverse all the three sorted list and perform the operation mentioned above. At the end traverse the new_array and look for value equal to 3, these indexes are the intersection result.
Time Complexity : O(N) + O(N) + .. = O(N)
Space Complexity : O(maximum_element - minimum_element)
where,
N = number of elements in the array.
Given an array: [dog, cat, mouse]
what is the most elegant way to create:
[,,]
[,,mouse]
[,cat,]
[,cat,mouse]
[dog,,]
[dog,,mouse]
[dog,cat,]
[dog,cat,mouse]
I need this to work for any sized array.
This is essentially a binary counter, where array indices represent bits. This presumably lets me use some bitwise operation to count, but I can't see a nice way of translating this to array indices though.
Elegant? Why not Linq it.
public static IEnumerable<IEnumerable<T>> SubSetsOf<T>(IEnumerable<T> source)
{
if (!source.Any())
return Enumerable.Repeat(Enumerable.Empty<T>(), 1);
var element = source.Take(1);
var haveNots = SubSetsOf(source.Skip(1));
var haves = haveNots.Select(set => element.Concat(set));
return haves.Concat(haveNots);
}
string[] source = new string[] { "dog", "cat", "mouse" };
for (int i = 0; i < Math.Pow(2, source.Length); i++)
{
string[] combination = new string[source.Length];
for (int j = 0; j < source.Length; j++)
{
if ((i & (1 << (source.Length - j - 1))) != 0)
{
combination[j] = source[j];
}
}
Console.WriteLine("[{0}, {1}, {2}]", combination[0], combination[1], combination[2]);
}
You can use the BitArray class to easily access the bits in a number:
string[] animals = { "Dog", "Cat", "Mouse" };
List<string[]> result = new List<string[]>();
int cnt = 1 << animals.Length;
for (int i = 0; i < cnt; i++) {
string[] item = new string[animals.Length];
BitArray b = new BitArray(i);
for (int j = 0; j < item.Length; j++) {
item[j] = b[j] ? animals[j] : null;
}
result.Add(item);
}
static IEnumerable<IEnumerable<T>> GetSubsets<T>(IList<T> set)
{
var state = new BitArray(set.Count);
do
yield return Enumerable.Range(0, state.Count)
.Select(i => state[i] ? set[i] : default(T));
while (Increment(state));
}
static bool Increment(BitArray flags)
{
int x = flags.Count - 1;
while (x >= 0 && flags[x]) flags[x--] = false ;
if (x >= 0) flags[x] = true;
return x >= 0;
}
Usage:
foreach(var strings in GetSubsets(new[] { "dog", "cat", "mouse" }))
Console.WriteLine(string.Join(", ", strings.ToArray()));
Guffa's answer had the basic functionality that I was searching, however the line with
BitArray b = new BitArray(i);
did not work for me, it gave an ArgumentOutOfRangeException. Here's my slightly adjusted and working code:
string[] array = { "A", "B", "C","D" };
int count = 1 << array.Length; // 2^n
for (int i = 0; i < count; i++)
{
string[] items = new string[array.Length];
BitArray b = new BitArray(BitConverter.GetBytes(i));
for (int bit = 0; bit < array.Length; bit++) {
items[bit] = b[bit] ? array[bit] : "";
}
Console.WriteLine(String.Join("",items));
}
Here's a solution similar to David B's method, but perhaps more suitable if it's really a requirement that you get back sets with the original number of elements (even if empty):.
static public List<List<T>> GetSubsets<T>(IEnumerable<T> originalList)
{
if (originalList.Count() == 0)
return new List<List<T>>() { new List<T>() };
var setsFound = new List<List<T>>();
foreach (var list in GetSubsets(originalList.Skip(1)))
{
setsFound.Add(originalList.Take(1).Concat(list).ToList());
setsFound.Add(new List<T>() { default(T) }.Concat(list).ToList());
}
return setsFound;
}
If you pass in a list of three strings, you'll get back eight lists with three elements each (but some elements will be null).
Here's an easy-to-follow solution along the lines of your conception:
private static void Test()
{
string[] test = new string[3] { "dog", "cat", "mouse" };
foreach (var x in Subsets(test))
Console.WriteLine("[{0}]", string.Join(",", x));
}
public static IEnumerable<T[]> Subsets<T>(T[] source)
{
int max = 1 << source.Length;
for (int i = 0; i < max; i++)
{
T[] combination = new T[source.Length];
for (int j = 0; j < source.Length; j++)
{
int tailIndex = source.Length - j - 1;
combination[tailIndex] =
((i & (1 << j)) != 0) ? source[tailIndex] : default(T);
}
yield return combination;
}
}
This is a small change to Mehrdad's solution above:
static IEnumerable<T[]> GetSubsets<T>(T[] set) {
bool[] state = new bool[set.Length+1];
for (int x; !state[set.Length]; state[x] = true ) {
yield return Enumerable.Range(0, state.Length)
.Where(i => state[i])
.Select(i => set[i])
.ToArray();
for (x = 0; state[x]; state[x++] = false);
}
}
or with pointers
static IEnumerable<T[]> GetSubsets<T>(T[] set) {
bool[] state = new bool[set.Length+1];
for (bool *x; !state[set.Length]; *x = true ) {
yield return Enumerable.Range(0, state.Length)
.Where(i => state[i])
.Select(i => set[i])
.ToArray();
for (x = state; *x; *x++ = false);
}
}
I'm not very familiar with C# but I'm sure there's something like:
// input: Array A
foreach S in AllSubsetsOf1ToN(A.Length):
print (S.toArray().map(lambda x |> A[x]));
Ok, I've been told the answer above won't work. If you value elegance over efficiency, I would try recursion, in my crappy pseudocode:
Array_Of_Sets subsets(Array a)
{
if (a.length == 0)
return [new Set();] // emptyset
return subsets(a[1:]) + subsets(a[1:]) . map(lambda x |> x.add a[0])
}
Here is a variant of mqp's answer, that uses as state a BigInteger instead of an int, to avoid overflow for collections containing more than 30 elements:
using System.Numerics;
public static IEnumerable<IEnumerable<T>> GetSubsets<T>(IList<T> source)
{
BigInteger combinations = BigInteger.One << source.Count;
for (BigInteger i = 0; i < combinations; i++)
{
yield return Enumerable.Range(0, source.Count)
.Select(j => (i & (BigInteger.One << j)) != 0 ? source[j] : default);
}
}
Easy to understand version (with descriptions)
I assumed that source = {1,2,3,4}
public static IEnumerable<IEnumerable<T>> GetSubSets<T>(IEnumerable<T> source)
{
var result = new List<IEnumerable<T>>() { new List<T>() }; // empty cluster added
for (int i = 0; i < source.Count(); i++)
{
var elem = source.Skip(i).Take(1);
// for elem = 2
// and currently result = [ [],[1] ]
var matchUps = result.Select(x => x.Concat(elem));
//then matchUps => [ [2],[1,2] ]
result = result.Concat(matchUps).ToList();
// matchUps and result concat operation
// finally result = [ [],[1],[2],[1,2] ]
}
return result;
}
The way this is written, it is more of a Product (Cartesian product) rather than a list of all subsets.
You have three sets: (Empty,"dog"), (Empty,"cat"),(Empty,"mouse").
There are several posts on general solutions for products. As noted though, since you really just have 2 choices for each axis a single bit can represent the presence or not of the item.
So the total set of sets is all numbers from 0 to 2^N-1. If N < 31 an int will work.