The below code returns all distinct combinations based on the logic that 1,2,3 = 3,2,1 = 2,3,1, so it only returns 1 instance of that set of numbers.
public void GetPowersets()
{
List<int> ints = new List<int>()
{
1,2,2,3,3
};
var results = GetPowerSet(ints);
List<String> combinations = new List<String>();
foreach (var result in results)
{
StringBuilder sb = new StringBuilder();
foreach (var intValue in result.OrderBy(x => x))
{
sb.Append(intValue + ",");
}
combinations.Add(sb.ToString());
}
string c1 = string.Join("|", combinations.ToArray()).Replace(",|", "|");
//c1 = "|1|2|1,2|2|1,2|2,2|1,2,2|3|1,3|2,3|1,2,3|2,3|1,2,3|2,2,3|1,2,2,3|3|1,3|2,3|1,2,3|2,3|1,2,3|2,2,3|1,2,2,3|3,3|1,3,3|2,3,3|1,2,3,3|2,3,3|1,2,3,3|2,2,3,3|1,2,2,3,3,"
}
public IEnumerable<IEnumerable<int>> GetPowerSet(List<int> list)
{
return from m in Enumerable.Range(0, 1 << list.Count)
select
from i in Enumerable.Range(0, list.Count)
where (m & (1 << i)) != 0
select list[i];
}
This is the end result I am trying to achieve: (no duplicate rows of combinations: duplicate = 3,2,1 and 3,2,1 are the same thing. but 1,2,3 and 3,2,1 are NOT the same thing and both should be in the end result)
1 2 3 1,2 1,3 2,1 2,3 2,2 3,1 3,2 3,3 1,2,3 1,2,2 1,3,2 1,3,3 2,1,3 2,1,2 2,3,1 2,3,2 2,3,3 2,2,1 2,2,3 3,1,2 3,1,3 3,2,1 3,2,2 3,2,3 3,3,1 3,3,2 1,2,3,2 1,2,3,3 1,2,2,3 1,3,2,2 1,3,2,3 1,3,3,2 2,1,3,2 2,1,3,3 2,1,2,3 2,3,1,2 2,3,1,3 2,3,2,1 2,3,2,3 2,3,3,1 2,3,3,2 2,2,1,3 2,2,3,1 2,2,3,3 3,1,2,2 3,1,2,3 3,1,3,2 3,2,1,2 3,2,1,3 3,2,2,1 3,2,2,3 3,2,3,1 3,2,3,2 3,3,1,2 3,3,2,1 3,3,2,2 1,2,3,2,3 1,2,3,3,2 1,2,2,3,3 1,3,2,2,3 1,3,2,3,2 1,3,3,2,2 2,1,3,2,3 2,1,3,3,2 2,1,2,3,3 2,3,1,2,3 2,3,1,3,2 2,3,2,1,3 2,3,2,3,1 2,3,3,1,2 2,3,3,2,1 2,2,1,3,3 2,2,3,1,3 2,2,3,3,1 3,1,2,2,3 3,1,2,3,2 3,1,3,2,2 3,2,1,2,3 3,2,1,3,2 3,2,2,1,3 3,2,2,3,1 3,2,3,1,2 3,2,3,2,1 3,3,1,2,2 3,3,2,1,2 3,3,2,2,1
I wanted to change that logic so that it returns ALL instances of all number sets.
Below is my for loop implementation of this logic.
public List<List<int>> GetAllCombinationsOfAllSizes(List<int> ints)
{
List<List<int>> returnResult = new List<List<int>>();
var distinctInts = ints.Distinct().ToList();
for (int j = 0; j < distinctInts.Count(); j++)
{
var number = distinctInts[j];
var newList = new List<int>();
newList.Add(number);
returnResult.Add(newList);
var listMinusOneObject = ints.Select(x => x).ToList();
listMinusOneObject.Remove(listMinusOneObject.Where(x => x == number).First());
if (listMinusOneObject.Count() > 0)
{
_GetAllCombinationsOfAllSizes(listMinusOneObject, newList, ref returnResult);
}
}
return returnResult;
}
public void _GetAllCombinationsOfAllSizes(List<int> ints, List<int> growingList, ref List<List<int>> returnResult)
{
var distinctInts = ints.Distinct().ToList();
for (int j = 0; j < distinctInts.Count(); j++)
{
var number = distinctInts[j];
var newList = growingList.ToList();
newList.Add(number);
returnResult.Add(newList);
var listMinusOneObject = ints.Select(x => x).ToList();
listMinusOneObject.Remove(listMinusOneObject.Where(x => x == number).First());
if (listMinusOneObject.Count() > 0)
{
_GetAllCombinationsOfAllSizes(listMinusOneObject, newList, ref returnResult);
}
}
}
The above solution to my problem is slow and prone to running out of memory. This seems to happen when the number set gets too large, like when passing in 15 or more numbers.
I am looking for a review on the above posted code. I am specifically interested in where I went wrong in terms of performance, and how I could improve that. I am open to all sorts of suggestions and criticisms on my code and implementation. Additionally, I am curious if there is a way to utilize Linq to improve my above code.
1,1
and1,2,1
in the output? \$\endgroup\$