Related
I have a list of integers List<int> in my C# program. However, I know the number of items I have in my list only at runtime.
Let us say, for the sake of simplicity, my list is {1, 2, 3}
Now I need to generate all possible combinations as follows.
{1, 2, 3}
{1, 2}
{1, 3}
{2, 3}
{1}
{2}
{3}
Can somebody please help with this?
try this:
static void Main(string[] args)
{
GetCombination(new List<int> { 1, 2, 3 });
}
static void GetCombination(List<int> list)
{
double count = Math.Pow(2, list.Count);
for (int i = 1; i <= count - 1; i++)
{
string str = Convert.ToString(i, 2).PadLeft(list.Count, '0');
for (int j = 0; j < str.Length; j++)
{
if (str[j] == '1')
{
Console.Write(list[j]);
}
}
Console.WriteLine();
}
}
Assuming that all items within the initial collection are distinct, we can try using Linq in order to query; let's generalize the solution:
Code:
public static IEnumerable<T[]> Combinations<T>(IEnumerable<T> source) {
if (null == source)
throw new ArgumentNullException(nameof(source));
T[] data = source.ToArray();
return Enumerable
.Range(0, 1 << (data.Length))
.Select(index => data
.Where((v, i) => (index & (1 << i)) != 0)
.ToArray());
}
Demo:
var data = new char[] { 'A', 'B', 'C' };
var result = Combinations(data);
foreach (var item in result)
Console.WriteLine($"[{string.Join(", ", item)}]");
Outcome:
[]
[A]
[B]
[A, B]
[C]
[A, C]
[B, C]
[A, B, C]
If you want to exclude the initial empty array, put .Range(1, (1 << (data.Length)) - 1) instead of .Range(0, 1 << (data.Length))
Algorithm explanation:
Having a collection of collection.Length distinct items we get 2 ** collection.Length combinations (we can compute it as 1 << collection.Length):
mask - comments
------------------------------------
00..0000 - empty, no items are taken
00..0001 - 1st item taken
00..0010 - 2nd item taken
00..0011 - 1st and 2nd items are taken
00..0100 - 3d item taken
...
11..1111 - all items are taken
To generate all masks we can use direct Enumerable.Range(0, 1 << (data.Length)) Linq query. Now having index mask we should take item from the collection if and only if corresponding bit within index is set to 1:
011001001
^^ ^ ^
take 7, 6, 3, 0-th items from the collection
The code can be
.Select(index => data.Where((v, i) => (index & (1 << i)) != 0)
here for each item (v) in the collection data we check if i-th bit is set in the index (mask).
Here are two generic solutions for strongly typed lists that will return all unique combinations of list members (if you can solve this with simpler code, I salute you):
// Recursive
public static List<List<T>> GetAllCombos<T>(List<T> list)
{
List<List<T>> result = new List<List<T>>();
// head
result.Add(new List<T>());
result.Last().Add(list[0]);
if (list.Count == 1)
return result;
// tail
List<List<T>> tailCombos = GetAllCombos(list.Skip(1).ToList());
tailCombos.ForEach(combo =>
{
result.Add(new List<T>(combo));
combo.Add(list[0]);
result.Add(new List<T>(combo));
});
return result;
}
// Iterative, using 'i' as bitmask to choose each combo members
public static List<List<T>> GetAllCombos<T>(List<T> list)
{
int comboCount = (int) Math.Pow(2, list.Count) - 1;
List<List<T>> result = new List<List<T>>();
for (int i = 1; i < comboCount + 1; i++)
{
// make each combo here
result.Add(new List<T>());
for (int j = 0; j < list.Count; j++)
{
if ((i >> j) % 2 != 0)
result.Last().Add(list[j]);
}
}
return result;
}
// Example usage
List<List<int>> combos = GetAllCombos(new int[] { 1, 2, 3 }.ToList());
This answer uses the same algorithm as ojlovecd and (for his iterative solution) jaolho. The only thing I'm adding is an option to filter the results for a minimum number of items in the combinations. This can be useful, for example, if you are only interested in the combinations that contain at least two items.
Edit: As requested by #user3610374 a filter for the maximum number of items has been added.
Edit 2: As suggested by #stannius the algorithm has been changed to make it more efficient for cases where not all combinations are wanted.
/// <summary>
/// Method to create lists containing possible combinations of an input list of items. This is
/// basically copied from code by user "jaolho" on this thread:
/// http://stackoverflow.com/questions/7802822/all-possible-combinations-of-a-list-of-values
/// </summary>
/// <typeparam name="T">type of the items on the input list</typeparam>
/// <param name="inputList">list of items</param>
/// <param name="minimumItems">minimum number of items wanted in the generated combinations,
/// if zero the empty combination is included,
/// default is one</param>
/// <param name="maximumItems">maximum number of items wanted in the generated combinations,
/// default is no maximum limit</param>
/// <returns>list of lists for possible combinations of the input items</returns>
public static List<List<T>> ItemCombinations<T>(List<T> inputList, int minimumItems = 1,
int maximumItems = int.MaxValue)
{
int nonEmptyCombinations = (int)Math.Pow(2, inputList.Count) - 1;
List<List<T>> listOfLists = new List<List<T>>(nonEmptyCombinations + 1);
// Optimize generation of empty combination, if empty combination is wanted
if (minimumItems == 0)
listOfLists.Add(new List<T>());
if (minimumItems <= 1 && maximumItems >= inputList.Count)
{
// Simple case, generate all possible non-empty combinations
for (int bitPattern = 1; bitPattern <= nonEmptyCombinations; bitPattern++)
listOfLists.Add(GenerateCombination(inputList, bitPattern));
}
else
{
// Not-so-simple case, avoid generating the unwanted combinations
for (int bitPattern = 1; bitPattern <= nonEmptyCombinations; bitPattern++)
{
int bitCount = CountBits(bitPattern);
if (bitCount >= minimumItems && bitCount <= maximumItems)
listOfLists.Add(GenerateCombination(inputList, bitPattern));
}
}
return listOfLists;
}
/// <summary>
/// Sub-method of ItemCombinations() method to generate a combination based on a bit pattern.
/// </summary>
private static List<T> GenerateCombination<T>(List<T> inputList, int bitPattern)
{
List<T> thisCombination = new List<T>(inputList.Count);
for (int j = 0; j < inputList.Count; j++)
{
if ((bitPattern >> j & 1) == 1)
thisCombination.Add(inputList[j]);
}
return thisCombination;
}
/// <summary>
/// Sub-method of ItemCombinations() method to count the bits in a bit pattern. Based on this:
/// https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan
/// </summary>
private static int CountBits(int bitPattern)
{
int numberBits = 0;
while (bitPattern != 0)
{
numberBits++;
bitPattern &= bitPattern - 1;
}
return numberBits;
}
Here's a generic solution using recursion
public static ICollection<ICollection<T>> Permutations<T>(ICollection<T> list) {
var result = new List<ICollection<T>>();
if (list.Count == 1) { // If only one possible permutation
result.Add(list); // Add it and return it
return result;
}
foreach (var element in list) { // For each element in that list
var remainingList = new List<T>(list);
remainingList.Remove(element); // Get a list containing everything except of chosen element
foreach (var permutation in Permutations<T>(remainingList)) { // Get all possible sub-permutations
permutation.Add(element); // Add that element
result.Add(permutation);
}
}
return result;
}
I know this is an old post, but someone might find this helpful.
Another solution using Linq and recursion...
static void Main(string[] args)
{
List<List<long>> result = new List<List<long>>();
List<long> set = new List<long>() { 1, 2, 3, 4 };
GetCombination<long>(set, result);
result.Add(set);
IOrderedEnumerable<List<long>> sorted = result.OrderByDescending(s => s.Count);
sorted.ToList().ForEach(l => { l.ForEach(l1 => Console.Write(l1 + " ")); Console.WriteLine(); });
}
private static void GetCombination<T>(List<T> set, List<List<T>> result)
{
for (int i = 0; i < set.Count; i++)
{
List<T> temp = new List<T>(set.Where((s, index) => index != i));
if (temp.Count > 0 && !result.Where(l => l.Count == temp.Count).Any(l => l.SequenceEqual(temp)))
{
result.Add(temp);
GetCombination<T>(temp, result);
}
}
}
This is an improvement of #ojlovecd answer without using strings.
static void Main(string[] args)
{
GetCombination(new List<int> { 1, 2, 3 });
}
private static void GetCombination(List<int> list)
{
double count = Math.Pow(2, list.Count);
for (int i = 1; i <= count - 1; i++)
{
for (int j = 0; j < list.Count; j++)
{
int b = i & (1 << j);
if (b > 0)
{
Console.Write(list[j]);
}
}
Console.WriteLine();
}
}
Firstly, given a set of n elements, you compute all combinations of k elements out of it (nCk). You have to change the value of k from 1 to n to meet your requirement.
See this codeproject article for C# code for generating combinations.
In case, you are interested in developing the combination algorithm by yourself, check this SO question where there are a lot of links to the relevant material.
protected List<List<T>> AllCombos<T>(Func<List<T>, List<T>, bool> comparer, params T[] items)
{
List<List<T>> results = new List<List<T>>();
List<T> workingWith = items.ToList();
results.Add(workingWith);
items.ToList().ForEach((x) =>
{
results.Add(new List<T>() { x });
});
for (int i = 0; i < workingWith.Count(); i++)
{
T removed = workingWith[i];
workingWith.RemoveAt(i);
List<List<T>> nextResults = AllCombos2(comparer, workingWith.ToArray());
results.AddRange(nextResults);
workingWith.Insert(i, removed);
}
results = results.Where(x => x.Count > 0).ToList();
for (int i = 0; i < results.Count; i++)
{
List<T> list = results[i];
if (results.Where(x => comparer(x, list)).Count() > 1)
{
results.RemoveAt(i);
}
}
return results;
}
protected List<List<T>> AllCombos2<T>(Func<List<T>, List<T>, bool> comparer, params T[] items)
{
List<List<T>> results = new List<List<T>>();
List<T> workingWith = items.ToList();
if (workingWith.Count > 1)
{
results.Add(workingWith);
}
for (int i = 0; i < workingWith.Count(); i++)
{
T removed = workingWith[i];
workingWith.RemoveAt(i);
List<List<T>> nextResults = AllCombos2(comparer, workingWith.ToArray());
results.AddRange(nextResults);
workingWith.Insert(i, removed);
}
results = results.Where(x => x.Count > 0).ToList();
for (int i = 0; i < results.Count; i++)
{
List<T> list = results[i];
if (results.Where(x => comparer(x, list)).Count() > 1)
{
results.RemoveAt(i);
}
}
return results;
}
This worked for me, it's slightly more complex and actually takes a comparer callback function, and it's actually 2 functions, the difference being that the AllCombos adds the single item lists explicitly. It is very raw and can definitely be trimmed down but it gets the job done. Any refactoring suggestions are welcome. Thanks,
public class CombinationGenerator{
private readonly Dictionary<int, int> currentIndexesWithLevels = new Dictionary<int, int>();
private readonly LinkedList<List<int>> _combinationsList = new LinkedList<List<int>>();
private readonly int _combinationLength;
public CombinationGenerator(int combinationLength)
{
_combinationLength = combinationLength;
}
private void InitializeLevelIndexes(List<int> list)
{
for (int i = 0; i < _combinationLength; i++)
{
currentIndexesWithLevels.Add(i+1, i);
}
}
private void UpdateCurrentIndexesForLevels(int level)
{
int index;
if (level == 1)
{
index = currentIndexesWithLevels[level];
for (int i = level; i < _combinationLength + 1; i++)
{
index = index + 1;
currentIndexesWithLevels[i] = index;
}
}
else
{
int previousLevelIndex;
for (int i = level; i < _combinationLength + 1; i++)
{
if (i > level)
{
previousLevelIndex = currentIndexesWithLevels[i - 1];
currentIndexesWithLevels[i] = previousLevelIndex + 1;
}
else
{
index = currentIndexesWithLevels[level];
currentIndexesWithLevels[i] = index + 1;
}
}
}
}
public void FindCombinations(List<int> list, int level, Stack<int> stack)
{
int currentIndex;
InitializeLevelIndexes(list);
while (true)
{
currentIndex = currentIndexesWithLevels[level];
bool levelUp = false;
for (int i = currentIndex; i < list.Count; i++)
{
if (level < _combinationLength)
{
currentIndex = currentIndexesWithLevels[level];
MoveToUpperLevel(ref level, stack, list, currentIndex);
levelUp = true;
break;
}
levelUp = false;
stack.Push(list[i]);
if (stack.Count == _combinationLength)
{
AddCombination(stack);
stack.Pop();
}
}
if (!levelUp)
{
MoveToLowerLevel(ref level, stack, list, ref currentIndex);
while (currentIndex >= list.Count - 1)
{
if (level == 1)
{
AdjustStackCountToCurrentLevel(stack, level);
currentIndex = currentIndexesWithLevels[level];
if (currentIndex >= list.Count - 1)
{
return;
}
UpdateCurrentIndexesForLevels(level);
}
else
{
MoveToLowerLevel(ref level, stack, list, ref currentIndex);
}
}
}
}
}
private void AddCombination(Stack<int> stack)
{
List<int> listNew = new List<int>();
listNew.AddRange(stack);
_combinationsList.AddLast(listNew);
}
private void MoveToUpperLevel(ref int level, Stack<int> stack, List<int> list, int index)
{
stack.Push(list[index]);
level++;
}
private void MoveToLowerLevel(ref int level, Stack<int> stack, List<int> list, ref int currentIndex)
{
if (level != 1)
{
level--;
}
AdjustStackCountToCurrentLevel(stack, level);
UpdateCurrentIndexesForLevels(level);
currentIndex = currentIndexesWithLevels[level];
}
private void AdjustStackCountToCurrentLevel(Stack<int> stack, int currentLevel)
{
while (stack.Count >= currentLevel)
{
if (stack.Count != 0)
stack.Pop();
}
}
public void PrintPermutations()
{
int count = _combinationsList.Where(perm => perm.Count() == _combinationLength).Count();
Console.WriteLine("The number of combinations is " + count);
}
}
We can use recursion for combination/permutation problems involving string or integers.
public static void Main(string[] args)
{
IntegerList = new List<int> { 1, 2, 3, 4 };
PrintAllCombination(default(int), default(int));
}
public static List<int> IntegerList { get; set; }
public static int Length { get { return IntegerList.Count; } }
public static void PrintAllCombination(int position, int prefix)
{
for (int i = position; i < Length; i++)
{
Console.WriteLine(prefix * 10 + IntegerList[i]);
PrintAllCombination(i + 1, prefix * 10 + IntegerList[i]);
}
}
What about
static void Main(string[] args)
{
Combos(new [] { 1, 2, 3 });
}
static void Combos(int[] arr)
{
for (var i = 0; i <= Math.Pow(2, arr.Length); i++)
{
Console.WriteLine();
var j = i;
var idx = 0;
do
{
if ((j & 1) == 1) Console.Write($"{arr[idx]} ");
} while ((j >>= 1) > 0 && ++idx < arr.Length);
}
}
A slightly more generalised version for Linq using C# 7. Here filtering by items that have two elements.
static void Main(string[] args)
{
foreach (var vals in Combos(new[] { "0", "1", "2", "3" }).Where(v => v.Skip(1).Any() && !v.Skip(2).Any()))
Console.WriteLine(string.Join(", ", vals));
}
static IEnumerable<IEnumerable<T>> Combos<T>(T[] arr)
{
IEnumerable<T> DoQuery(long j, long idx)
{
do
{
if ((j & 1) == 1) yield return arr[idx];
} while ((j >>= 1) > 0 && ++idx < arr.Length);
}
for (var i = 0; i < Math.Pow(2, arr.Length); i++)
yield return DoQuery(i, 0);
}
Here is how I did it.
public static List<List<int>> GetCombination(List<int> lst, int index, int count)
{
List<List<int>> combinations = new List<List<int>>();
List<int> comb;
if (count == 0 || index == lst.Count)
{
return null;
}
for (int i = index; i < lst.Count; i++)
{
comb = new List<int>();
comb.Add(lst.ElementAt(i));
combinations.Add(comb);
var rest = GetCombination(lst,i + 1, count - 1);
if (rest != null)
{
foreach (var item in rest)
{
combinations.Add(comb.Union(item).ToList());
}
}
}
return combinations;
}
You call it as :
List<int> lst= new List<int>(new int[]{ 1, 2, 3, 4 });
var combinations = GetCombination(lst, 0, lst.Length)
I just run into a situation where I needed to do this, this is what I came up with:
private static List<string> GetCombinations(List<string> elements)
{
List<string> combinations = new List<string>();
combinations.AddRange(elements);
for (int i = 0; i < elements.Count - 1; i++)
{
combinations = (from combination in combinations
join element in elements on 1 equals 1
let value = string.Join(string.Empty, $"{combination}{element}".OrderBy(c => c).Distinct())
select value).Distinct().ToList();
}
return combinations;
}
It may be not too efficient, and it sure has room for improvement, but gets the job done!
List<string> elements = new List<string> { "1", "2", "3" };
List<string> combinations = GetCombinations(elements);
foreach (string combination in combinations)
{
System.Console.Write(combination);
}
This is an improved version based on the answer from ojlovecd using extension methods:
public static class ListExtensions
{
public static IEnumerable<List<T>> GetCombinations<T>(
this List<T> valuesToCombine)
{
var count = Math.Pow(2, valuesToCombine.Count);
for(var i = 1; i <= count; i++)
{
var itemFlagList = i.ToBinaryString(valuesToCombine.Count())
.Select(x => x == '1').ToList();
yield return GetCombinationByFlagList(valuesToCombine, itemFlagList)
.ToList();
}
}
private static IEnumerable<T> GetCombinationByFlagList<T>(
List<T> valuesToCombine, List<bool> flagList)
{
for (var i = 0; i < valuesToCombine.Count; i++)
{
if (!flagList[i]) continue;
yield return valuesToCombine.ElementAt(i);
}
}
}
public static class IntegerExtensions
{
public static string ToBinaryString(this int value, int length)
{
return Convert.ToString(value, 2).ToString().PadLeft(length, '0');
}
}
Usage:
var numbersList = new List<int>() { 1, 2, 3 };
var combinations = numbersList.GetCombinations();
foreach (var combination in combinations)
{
System.Console.WriteLine(string.Join(",", combination));
}
Output:
3
2
2,3
1
1,3
1,2
1,2,3
The idea is to basically use some flags to keep track of which items were already added to the combination. So in case of 1, 2 & 3, the following binary strings are generated in order to indicate whether an item should be included or excluded:
001, 010, 011, 100, 101, 110 & 111
I'd like to suggest an approach that I find to be quite intuitive and easy to read. (Note: It is slower than the currently accepted solution.)
It is built on the idea that for each integer in the list, we need to extend the so-far-aggregated resulting combination list with
all currently existing combinations, each extended with the given integer
a single "combination" of that integer alone
Here, I am using .Aggregate() with a seed that is an IEnumerable<IEnumerable<int>> containing a single, empty collection entry. That empty entry lets us easily do the two steps above simultaneously. The empty collection entry can be skipped after the resulting combination collection has been aggregated.
It goes like this:
var emptyCollection = Enumerable.Empty<IEnumerable<int>>();
var emptyCombination = Enumerable.Empty<int>();
IEnumerable<int[]> combinations = list
.Aggregate(emptyCollection.Append(emptyCombination),
( acc, next ) => acc.Concat(acc.Select(entry => entry.Append(next))))
.Skip(1) // skip the initial, empty combination
.Select(comb => comb.ToArray());
For each entry in the input integer list { 1, 2, 3 }, the accumulation progresses as follows:
next = 1
{ { } }.Concat({ { }.Append(1) })
{ { } }.Concat({ { 1 } })
{ { }, { 1 } } // acc
next = 2
{ { }, { 1 } }.Concat({ { }.Append(2), { 1 }.Append(2) })
{ { }, { 1 } }.Concat({ { 2 }, { 1, 2 } })
{ { }, { 1 }, { 2 }, { 1, 2 } } // acc
next = 3
{ { }, { 1 }, { 2 }, { 1, 2 } }.Concat({ { }.Append(3), { 1 }.Append(3), { 2 }.Append(3), { 1, 2 }.Append(3) })
{ { }, { 1 }, { 2 }, { 1, 2 } }.Concat({ { 3 }, { 1, 3 }, { 2, 3 }, { 1, 2, 3 } })
{ { }, { 1 }, { 2 }, { 1, 2 }, { 3 }, { 1, 3 }, { 2, 3 }, { 1, 2, 3 } } // acc
Skipping the first (empty) entry, we are left with the following collection:
1
2
1 2
3
1 3
2 3
1 2 3
, which can easily be ordered by collection length and collection entry sum for a clearer overview.
Example fiddle here.
Some of the solutions here are truly ingenious; especially the ones that use bitmaps.
But I found that in practice these algos
aren't easy to modify if a specific range of lengths needed (e.g. all variations of 3 to 5 choices from an input set of 8 elements)
can't handle LARGE input lists (and return empty or singleton results instead of throwing exception); and
can be tricky to debug.
So I decided to write something not as clever as the other people here.
My more basic approach recognises that the set of Variations(1 to maxLength) is simply a UNION of all fixed-length Variations of each length 1 to maxLength:
i.e
Variations(1 to maxLength) = Variations(1) + Variations(2) + ... + Variations(maxLength)
So you can do a "choose K from N" for each required length (for each K in (1, 2, 3, ..., maxLength)) and then just do a Union of these separate results to yield a List of Lists.
This resulting code intends to be easy to understand and to maintain:
/// <summary>
/// Generates ALL variations of length between minLength and maxLength (inclusive)
/// Relies on Combinatorics library to generate each set of Variations
/// Nuget https://www.nuget.org/packages/Combinatorics/
/// Excellent more general references (without this solution):
/// https://www.codeproject.com/Articles/26050/Permutations-Combinations-and-Variations-using-C-G
/// Self-authored solution.
/// </summary>
/// <typeparam name="T">Any type without any constraints.</typeparam>
/// <param name="sourceList">The source list of elements to be combined.</param>
/// <param name="minLength">The minimum length of variation required.</param>
/// <param name="maxLength">The maximum length of variation required.</param>
/// <returns></returns>
public static List<List<T>> GenerateVariations<T>(this IEnumerable<T> sourceList, int minLength, int maxLength)
{
List<List<T>> finalUnion = new();
foreach (int length in Enumerable.Range(minLength, maxLength))
{
Variations<T> variations = new Variations<T>(sourceList, length, GenerateOption.WithoutRepetition);
foreach (var variation in variations)
{
var list = variation.ToList<T>();
finalUnion.Add(list);
}
}
Debug.WriteLine(sourceList.Count() + " source " + typeof(T).Name + " yielded " + finalUnion.Count());
return finalUnion;
}
Happy to receive comments (good and bad). Maybe there's a more succint way to achieve this in LINQ? Maybe the really smart people here can marry their approach with my more basic one?
Please find very very simple solution without recursion and which dont eat RAM.
Unique Combinations
I have this method Shuffle that supposes to return a set of random numbers which was displayed in the above method but the numbers need to be displayed in a mixed format.
The first method works well since the number are being displayed correctly in the set of range but this method Shuffle is not returning them in a mixed format.
Example:
The first method returned: 1, 2, 3, 4, 5
This method needs to return 2, 1, 4, 5, 3
public int[] Shuffle(int[] Sequence)
{
int[] Array = new int[Sequence.Length];
for(int s=0; s < Array.Length-1; s++){
int GenObj = GenerateAnotherNum (0, Array.Length + 1);
Array[s] = Sequence[GenObj];
Sequence[GenObj] = Array[s];
}
return Sequence;
}
You have several problems here: all zeroes array, range and swap procedure
Algorithm:
https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
Code:
// probably "static" should be added (depends on GenerateAnotherNum routine)
public int[] Shuffle(int[] Sequence)
{
// public method's arguments validation
if (null == Sequence)
throw new ArgumentNullException(nameof(Sequence));
// No need in Array if you want to modify Sequence
for(int s = 0; s < Sequence.Length - 1; s++)
{
int GenObj = GenerateAnotherNum(s, Sequence.Length); // pleace, note the range
// swap procedure: note, var h to store initial Sequence[s] value
var h = Sequence[s];
Sequence[s] = Sequence[GenObj];
Sequence[GenObj] = h;
}
return Sequence;
}
Demo:
// Random(0) - we want to reproduce the results in the demo
private static Random random = new Random(0);
// Let unknown GenerateAnotherNum be a random
private static int GenerateAnotherNum(int from, int to) => random.Next(from, to);
...
int[] array = new int[] { 1, 2, 3, 4, 5 };
string result = string.Join(", ", Shuffle(array));
Console.Write(result);
Outcome:
4, 5, 2, 3, 1
public static class Shuffler<T>
{
private static Random r = new Random();
public static T[] Shuffle(T[] items)
{
for(int i = 0; i < items.Length - 1; i++)
{
int pos = r.Next(i, items.Length);
T temp = items[i];
items[i] = items[pos];
items[pos] = temp;
}
return items;
}
public static IList<T> Shuffle(IList<T> items)
{
for(int i = 0; i < items.Count - 1; i++)
{
int pos = r.Next(i, items.Count);
T temp = items[i];
items[i] = items[pos];
items[pos] = temp;
}
return items;
}
}
I am trying to create a method that will return all subsets of a set.
For example if I have the collection 10,20,30 I will like to get the following output
return new List<List<int>>()
{
new List<int>(){10},
new List<int>(){20},
new List<int>(){30},
new List<int>(){10,20},
new List<int>(){10,30},
new List<int>(){20,30},
//new List<int>(){20,10}, that substet already exists
// new List<int>(){30,20}, that subset already exists
new List<int>(){10,20,30}
};
because the collection can also be a collection of strings for instance I want to create a generic method. This is what I have worked out based on this solution.
static void Main(string[] args)
{
Foo<int>(new int[] { 10, 20, 30});
}
static List<List<T>> Foo<T>(T[] set)
{
// Init list
List<List<T>> subsets = new List<List<T>>();
// Loop over individual elements
for (int i = 1; i < set.Length; i++)
{
subsets.Add(new List<T>(){set[i - 1]});
List<List<T>> newSubsets = new List<List<T>>();
// Loop over existing subsets
for (int j = 0; j < subsets.Count; j++)
{
var tempList = new List<T>();
tempList.Add(subsets[j][0]);
tempList.Add(subsets[i][0]);
var newSubset = tempList;
newSubsets.Add(newSubset);
}
subsets.AddRange(newSubsets);
}
// Add in the last element
//subsets.Add(set[set.Length - 1]);
//subsets.Sort();
//Console.WriteLine(string.Join(Environment.NewLine, subsets));
return null;
}
Edit
Sorry that is wrong I still get duplicates...
static List<List<T>> GetSubsets<T>(IEnumerable<T> Set)
{
var set = Set.ToList<T>();
// Init list
List<List<T>> subsets = new List<List<T>>();
subsets.Add(new List<T>()); // add the empty set
// Loop over individual elements
for (int i = 1; i < set.Count; i++)
{
subsets.Add(new List<T>(){set[i - 1]});
List<List<T>> newSubsets = new List<List<T>>();
// Loop over existing subsets
for (int j = 0; j < subsets.Count; j++)
{
var newSubset = new List<T>();
foreach(var temp in subsets[j])
newSubset.Add(temp);
newSubset.Add(set[i]);
newSubsets.Add(newSubset);
}
subsets.AddRange(newSubsets);
}
// Add in the last element
subsets.Add(new List<T>(){set[set.Count - 1]});
//subsets.Sort();
return subsets;
}
Then I could call that method as:
This is a basic algorithm which i used the below technique to make a single player scrabble word solver (the newspaper ones).
Let your set have n elements. Increment an integer starting from 0 to 2^n. For each generater number bitmask each position of the integer. If the i th position of the integer is 1 then select the i th element of the set. For each generated integer from 0 to 2^n doing the above bitmasting and selection will get you all the subsets.
Here is a post: http://phoxis.org/2009/10/13/allcombgen/
Here is an adaptation of the code provided by Marvin Mendes in this answer but refactored into a single method with an iterator block.
public static IEnumerable<IEnumerable<T>> Subsets<T>(IEnumerable<T> source)
{
List<T> list = source.ToList();
int length = list.Count;
int max = (int)Math.Pow(2, list.Count);
for (int count = 0; count < max; count++)
{
List<T> subset = new List<T>();
uint rs = 0;
while (rs < length)
{
if ((count & (1u << (int)rs)) > 0)
{
subset.Add(list[(int)rs]);
}
rs++;
}
yield return subset;
}
}
I know that this question is a little old but i was looking for a answer and dont find any good here, so i want to share this solution that is an adaptation found in this blog: http://praseedp.blogspot.com.br/2010/02/subset-generation-in-c.html
I Only transform the class into a generic class:
public class SubSet<T>
{
private IList<T> _list;
private int _length;
private int _max;
private int _count;
public SubSet(IList<T> list)
{
if (list== null)
throw new ArgumentNullException("lista");
_list = list;
_length = _list.Count;
_count = 0;
_max = (int)Math.Pow(2, _length);
}
public IList<T> Next()
{
if (_count == _max)
{
return null;
}
uint rs = 0;
IList<T> l = new List<T>();
while (rs < _length)
{
if ((_count & (1u << (int)rs)) > 0)
{
l.Add(_list[(int)rs]);
}
rs++;
}
_count++;
return l;
}
}
To use this code you can do like something that:
List<string> lst = new List<string>();
lst.AddRange(new string[] {"A", "B", "C" });
SubSet<string> subs = new SubSet<string>(lst);
IList<string> l = subs.Next();
while (l != null)
{
DoSomething(l);
l = subs.Next();
}
Just remember: this code still be an O(2^n) and if you pass something like 20 elements in the list you will get 2^20= 1048576 subsets!
Edit:
As Servy sugest i add an implementation with interator block to use with Linq an foreach, the new class is like this:
private class SubSet<T> : IEnumerable<IEnumerable<T>>
{
private IList<T> _list;
private int _length;
private int _max;
private int _count;
public SubSet(IEnumerable<T> list)
{
if (list == null)
throw new ArgumentNullException("list");
_list = new List<T>(list);
_length = _list.Count;
_count = 0;
_max = (int)Math.Pow(2, _length);
}
public int Count
{
get { return _max; }
}
private IList<T> Next()
{
if (_count == _max)
{
return null;
}
uint rs = 0;
IList<T> l = new List<T>();
while (rs < _length)
{
if ((_count & (1u << (int)rs)) > 0)
{
l.Add(_list[(int)rs]);
}
rs++;
}
_count++;
return l;
}
public IEnumerator<IEnumerable<T>> GetEnumerator()
{
IList<T> subset;
while ((subset = Next()) != null)
{
yield return subset;
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
and you now can use it like this:
List<string> lst = new List<string>();
lst.AddRange(new string[] {"A", "B", "C" });
SubSet<string> subs = new SubSet<string>(lst);
foreach(IList<string> l in subs)
{
DoSomething(l);
}
Thanks Servy for the advice.
It Doesn't give duplicate value;
Don't add a value of the int array at the start of the subsets
Correct program is as follows:
class Program
{
static HashSet<List<int>> SubsetMaker(int[] a, int sum)
{
var set = a.ToList<int>();
HashSet<List<int>> subsets = new HashSet<List<int>>();
subsets.Add(new List<int>());
for (int i =0;i<set.Count;i++)
{
//subsets.Add(new List<int>() { set[i]});
HashSet<List<int>> newSubsets = new HashSet<List<int>>();
for (int j = 0; j < subsets.Count; j++)
{
var newSubset = new List<int>();
foreach (var temp in subsets.ElementAt(j))
{
newSubset.Add(temp);
}
newSubset.Add(set[i]);
newSubsets.Add(newSubset);
}
Console.WriteLine("New Subset");
foreach (var t in newSubsets)
{
var temp = string.Join<int>(",", t);
temp = "{" + temp + "}";
Console.WriteLine(temp);
}
Console.ReadLine();
subsets.UnionWith(newSubsets);
}
//subsets.Add(new List<int>() { set[set.Count - 1] });
//subsets=subsets.;
return subsets;
}
static void Main(string[] args)
{
int[] b = new int[] { 1,2,3 };
int suma = 6;
var test = SubsetMaker(b, suma);
Console.WriteLine("Printing final set...");
foreach (var t in test)
{
var temp = string.Join<int>(",", t);
temp = "{" + temp + "}";
Console.WriteLine(temp);
}
Console.ReadLine();
}
}
You don't want to return a set of lists, you want to use java's set type. Set already does part of what you are looking for by holding only one unique element of each type. So you can't add 20 twice for instance. It is an unordered type, so what you might do is write a combinatoric function that creates a bunch of sets and then return a list that includes alist of those.
Get all subsets of a collection of a specific subsetlength:
public static IEnumerable<IEnumerable<T>> GetPermutations<T>(IEnumerable<T> list, int length) where T : IComparable
{
if (length == 1) return list.Select(t => new T[] { t });
return GetPermutations(list, length - 1).SelectMany(t => list.Where(e => t.All(g => g.CompareTo(e) != 0)), (t1, t2) => t1.Concat(new T[] { t2 }));
}
public static IEnumerable<IEnumerable<T>> GetOrderedSubSets<T>(IEnumerable<T> list, int length) where T : IComparable
{
if (length == 1) return list.Select(t => new T[] { t });
return GetOrderedSubSets(list, length - 1).SelectMany(t => list.Where(e => t.All(g => g.CompareTo(e) == -1)), (t1, t2) => t1.Concat(new T[] { t2 }));
}
Testcode:
List<int> set = new List<int> { 1, 2, 3 };
foreach (var x in GetPermutations(set, 3))
{
Console.WriteLine(string.Join(", ", x));
}
Console.WriteLine();
foreach (var x in GetPermutations(set, 2))
{
Console.WriteLine(string.Join(", ", x));
}
Console.WriteLine();
foreach (var x in GetOrderedSubSets(set, 2))
{
Console.WriteLine(string.Join(", ", x));
}
Test results:
1, 2, 3
1, 3, 2
2, 1, 3
2, 3, 1
3, 1, 2
3, 2, 1
1, 2
1, 3
2, 1
2, 3
3, 1
3, 2
1, 2
1, 3
2, 3
A simple algorithm based upon recursion:
private static List<List<int>> GetPowerList(List<int> a)
{
int n = a.Count;
var sublists = new List<List<int>>() { new List<int>() };
for (int i = 0; i < n; i++)
{
for (int j = i; j < n; j++)
{
var first = a[i];
var last = a[j];
if ((j - i) > 1)
{
sublists.AddRange(GetPowerList(a
.GetRange(i + 1, j - i - 1))
.Select(l => l
.Prepend(first)
.Append(last).ToList()));
}
else sublists.Add(a.GetRange(i,j - i + 1));
}
}
return sublists;
}
I have a list of integers List<int> in my C# program. However, I know the number of items I have in my list only at runtime.
Let us say, for the sake of simplicity, my list is {1, 2, 3}
Now I need to generate all possible combinations as follows.
{1, 2, 3}
{1, 2}
{1, 3}
{2, 3}
{1}
{2}
{3}
Can somebody please help with this?
try this:
static void Main(string[] args)
{
GetCombination(new List<int> { 1, 2, 3 });
}
static void GetCombination(List<int> list)
{
double count = Math.Pow(2, list.Count);
for (int i = 1; i <= count - 1; i++)
{
string str = Convert.ToString(i, 2).PadLeft(list.Count, '0');
for (int j = 0; j < str.Length; j++)
{
if (str[j] == '1')
{
Console.Write(list[j]);
}
}
Console.WriteLine();
}
}
Assuming that all items within the initial collection are distinct, we can try using Linq in order to query; let's generalize the solution:
Code:
public static IEnumerable<T[]> Combinations<T>(IEnumerable<T> source) {
if (null == source)
throw new ArgumentNullException(nameof(source));
T[] data = source.ToArray();
return Enumerable
.Range(0, 1 << (data.Length))
.Select(index => data
.Where((v, i) => (index & (1 << i)) != 0)
.ToArray());
}
Demo:
var data = new char[] { 'A', 'B', 'C' };
var result = Combinations(data);
foreach (var item in result)
Console.WriteLine($"[{string.Join(", ", item)}]");
Outcome:
[]
[A]
[B]
[A, B]
[C]
[A, C]
[B, C]
[A, B, C]
If you want to exclude the initial empty array, put .Range(1, (1 << (data.Length)) - 1) instead of .Range(0, 1 << (data.Length))
Algorithm explanation:
Having a collection of collection.Length distinct items we get 2 ** collection.Length combinations (we can compute it as 1 << collection.Length):
mask - comments
------------------------------------
00..0000 - empty, no items are taken
00..0001 - 1st item taken
00..0010 - 2nd item taken
00..0011 - 1st and 2nd items are taken
00..0100 - 3d item taken
...
11..1111 - all items are taken
To generate all masks we can use direct Enumerable.Range(0, 1 << (data.Length)) Linq query. Now having index mask we should take item from the collection if and only if corresponding bit within index is set to 1:
011001001
^^ ^ ^
take 7, 6, 3, 0-th items from the collection
The code can be
.Select(index => data.Where((v, i) => (index & (1 << i)) != 0)
here for each item (v) in the collection data we check if i-th bit is set in the index (mask).
Here are two generic solutions for strongly typed lists that will return all unique combinations of list members (if you can solve this with simpler code, I salute you):
// Recursive
public static List<List<T>> GetAllCombos<T>(List<T> list)
{
List<List<T>> result = new List<List<T>>();
// head
result.Add(new List<T>());
result.Last().Add(list[0]);
if (list.Count == 1)
return result;
// tail
List<List<T>> tailCombos = GetAllCombos(list.Skip(1).ToList());
tailCombos.ForEach(combo =>
{
result.Add(new List<T>(combo));
combo.Add(list[0]);
result.Add(new List<T>(combo));
});
return result;
}
// Iterative, using 'i' as bitmask to choose each combo members
public static List<List<T>> GetAllCombos<T>(List<T> list)
{
int comboCount = (int) Math.Pow(2, list.Count) - 1;
List<List<T>> result = new List<List<T>>();
for (int i = 1; i < comboCount + 1; i++)
{
// make each combo here
result.Add(new List<T>());
for (int j = 0; j < list.Count; j++)
{
if ((i >> j) % 2 != 0)
result.Last().Add(list[j]);
}
}
return result;
}
// Example usage
List<List<int>> combos = GetAllCombos(new int[] { 1, 2, 3 }.ToList());
This answer uses the same algorithm as ojlovecd and (for his iterative solution) jaolho. The only thing I'm adding is an option to filter the results for a minimum number of items in the combinations. This can be useful, for example, if you are only interested in the combinations that contain at least two items.
Edit: As requested by #user3610374 a filter for the maximum number of items has been added.
Edit 2: As suggested by #stannius the algorithm has been changed to make it more efficient for cases where not all combinations are wanted.
/// <summary>
/// Method to create lists containing possible combinations of an input list of items. This is
/// basically copied from code by user "jaolho" on this thread:
/// http://stackoverflow.com/questions/7802822/all-possible-combinations-of-a-list-of-values
/// </summary>
/// <typeparam name="T">type of the items on the input list</typeparam>
/// <param name="inputList">list of items</param>
/// <param name="minimumItems">minimum number of items wanted in the generated combinations,
/// if zero the empty combination is included,
/// default is one</param>
/// <param name="maximumItems">maximum number of items wanted in the generated combinations,
/// default is no maximum limit</param>
/// <returns>list of lists for possible combinations of the input items</returns>
public static List<List<T>> ItemCombinations<T>(List<T> inputList, int minimumItems = 1,
int maximumItems = int.MaxValue)
{
int nonEmptyCombinations = (int)Math.Pow(2, inputList.Count) - 1;
List<List<T>> listOfLists = new List<List<T>>(nonEmptyCombinations + 1);
// Optimize generation of empty combination, if empty combination is wanted
if (minimumItems == 0)
listOfLists.Add(new List<T>());
if (minimumItems <= 1 && maximumItems >= inputList.Count)
{
// Simple case, generate all possible non-empty combinations
for (int bitPattern = 1; bitPattern <= nonEmptyCombinations; bitPattern++)
listOfLists.Add(GenerateCombination(inputList, bitPattern));
}
else
{
// Not-so-simple case, avoid generating the unwanted combinations
for (int bitPattern = 1; bitPattern <= nonEmptyCombinations; bitPattern++)
{
int bitCount = CountBits(bitPattern);
if (bitCount >= minimumItems && bitCount <= maximumItems)
listOfLists.Add(GenerateCombination(inputList, bitPattern));
}
}
return listOfLists;
}
/// <summary>
/// Sub-method of ItemCombinations() method to generate a combination based on a bit pattern.
/// </summary>
private static List<T> GenerateCombination<T>(List<T> inputList, int bitPattern)
{
List<T> thisCombination = new List<T>(inputList.Count);
for (int j = 0; j < inputList.Count; j++)
{
if ((bitPattern >> j & 1) == 1)
thisCombination.Add(inputList[j]);
}
return thisCombination;
}
/// <summary>
/// Sub-method of ItemCombinations() method to count the bits in a bit pattern. Based on this:
/// https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan
/// </summary>
private static int CountBits(int bitPattern)
{
int numberBits = 0;
while (bitPattern != 0)
{
numberBits++;
bitPattern &= bitPattern - 1;
}
return numberBits;
}
Here's a generic solution using recursion
public static ICollection<ICollection<T>> Permutations<T>(ICollection<T> list) {
var result = new List<ICollection<T>>();
if (list.Count == 1) { // If only one possible permutation
result.Add(list); // Add it and return it
return result;
}
foreach (var element in list) { // For each element in that list
var remainingList = new List<T>(list);
remainingList.Remove(element); // Get a list containing everything except of chosen element
foreach (var permutation in Permutations<T>(remainingList)) { // Get all possible sub-permutations
permutation.Add(element); // Add that element
result.Add(permutation);
}
}
return result;
}
I know this is an old post, but someone might find this helpful.
Another solution using Linq and recursion...
static void Main(string[] args)
{
List<List<long>> result = new List<List<long>>();
List<long> set = new List<long>() { 1, 2, 3, 4 };
GetCombination<long>(set, result);
result.Add(set);
IOrderedEnumerable<List<long>> sorted = result.OrderByDescending(s => s.Count);
sorted.ToList().ForEach(l => { l.ForEach(l1 => Console.Write(l1 + " ")); Console.WriteLine(); });
}
private static void GetCombination<T>(List<T> set, List<List<T>> result)
{
for (int i = 0; i < set.Count; i++)
{
List<T> temp = new List<T>(set.Where((s, index) => index != i));
if (temp.Count > 0 && !result.Where(l => l.Count == temp.Count).Any(l => l.SequenceEqual(temp)))
{
result.Add(temp);
GetCombination<T>(temp, result);
}
}
}
This is an improvement of #ojlovecd answer without using strings.
static void Main(string[] args)
{
GetCombination(new List<int> { 1, 2, 3 });
}
private static void GetCombination(List<int> list)
{
double count = Math.Pow(2, list.Count);
for (int i = 1; i <= count - 1; i++)
{
for (int j = 0; j < list.Count; j++)
{
int b = i & (1 << j);
if (b > 0)
{
Console.Write(list[j]);
}
}
Console.WriteLine();
}
}
Firstly, given a set of n elements, you compute all combinations of k elements out of it (nCk). You have to change the value of k from 1 to n to meet your requirement.
See this codeproject article for C# code for generating combinations.
In case, you are interested in developing the combination algorithm by yourself, check this SO question where there are a lot of links to the relevant material.
protected List<List<T>> AllCombos<T>(Func<List<T>, List<T>, bool> comparer, params T[] items)
{
List<List<T>> results = new List<List<T>>();
List<T> workingWith = items.ToList();
results.Add(workingWith);
items.ToList().ForEach((x) =>
{
results.Add(new List<T>() { x });
});
for (int i = 0; i < workingWith.Count(); i++)
{
T removed = workingWith[i];
workingWith.RemoveAt(i);
List<List<T>> nextResults = AllCombos2(comparer, workingWith.ToArray());
results.AddRange(nextResults);
workingWith.Insert(i, removed);
}
results = results.Where(x => x.Count > 0).ToList();
for (int i = 0; i < results.Count; i++)
{
List<T> list = results[i];
if (results.Where(x => comparer(x, list)).Count() > 1)
{
results.RemoveAt(i);
}
}
return results;
}
protected List<List<T>> AllCombos2<T>(Func<List<T>, List<T>, bool> comparer, params T[] items)
{
List<List<T>> results = new List<List<T>>();
List<T> workingWith = items.ToList();
if (workingWith.Count > 1)
{
results.Add(workingWith);
}
for (int i = 0; i < workingWith.Count(); i++)
{
T removed = workingWith[i];
workingWith.RemoveAt(i);
List<List<T>> nextResults = AllCombos2(comparer, workingWith.ToArray());
results.AddRange(nextResults);
workingWith.Insert(i, removed);
}
results = results.Where(x => x.Count > 0).ToList();
for (int i = 0; i < results.Count; i++)
{
List<T> list = results[i];
if (results.Where(x => comparer(x, list)).Count() > 1)
{
results.RemoveAt(i);
}
}
return results;
}
This worked for me, it's slightly more complex and actually takes a comparer callback function, and it's actually 2 functions, the difference being that the AllCombos adds the single item lists explicitly. It is very raw and can definitely be trimmed down but it gets the job done. Any refactoring suggestions are welcome. Thanks,
public class CombinationGenerator{
private readonly Dictionary<int, int> currentIndexesWithLevels = new Dictionary<int, int>();
private readonly LinkedList<List<int>> _combinationsList = new LinkedList<List<int>>();
private readonly int _combinationLength;
public CombinationGenerator(int combinationLength)
{
_combinationLength = combinationLength;
}
private void InitializeLevelIndexes(List<int> list)
{
for (int i = 0; i < _combinationLength; i++)
{
currentIndexesWithLevels.Add(i+1, i);
}
}
private void UpdateCurrentIndexesForLevels(int level)
{
int index;
if (level == 1)
{
index = currentIndexesWithLevels[level];
for (int i = level; i < _combinationLength + 1; i++)
{
index = index + 1;
currentIndexesWithLevels[i] = index;
}
}
else
{
int previousLevelIndex;
for (int i = level; i < _combinationLength + 1; i++)
{
if (i > level)
{
previousLevelIndex = currentIndexesWithLevels[i - 1];
currentIndexesWithLevels[i] = previousLevelIndex + 1;
}
else
{
index = currentIndexesWithLevels[level];
currentIndexesWithLevels[i] = index + 1;
}
}
}
}
public void FindCombinations(List<int> list, int level, Stack<int> stack)
{
int currentIndex;
InitializeLevelIndexes(list);
while (true)
{
currentIndex = currentIndexesWithLevels[level];
bool levelUp = false;
for (int i = currentIndex; i < list.Count; i++)
{
if (level < _combinationLength)
{
currentIndex = currentIndexesWithLevels[level];
MoveToUpperLevel(ref level, stack, list, currentIndex);
levelUp = true;
break;
}
levelUp = false;
stack.Push(list[i]);
if (stack.Count == _combinationLength)
{
AddCombination(stack);
stack.Pop();
}
}
if (!levelUp)
{
MoveToLowerLevel(ref level, stack, list, ref currentIndex);
while (currentIndex >= list.Count - 1)
{
if (level == 1)
{
AdjustStackCountToCurrentLevel(stack, level);
currentIndex = currentIndexesWithLevels[level];
if (currentIndex >= list.Count - 1)
{
return;
}
UpdateCurrentIndexesForLevels(level);
}
else
{
MoveToLowerLevel(ref level, stack, list, ref currentIndex);
}
}
}
}
}
private void AddCombination(Stack<int> stack)
{
List<int> listNew = new List<int>();
listNew.AddRange(stack);
_combinationsList.AddLast(listNew);
}
private void MoveToUpperLevel(ref int level, Stack<int> stack, List<int> list, int index)
{
stack.Push(list[index]);
level++;
}
private void MoveToLowerLevel(ref int level, Stack<int> stack, List<int> list, ref int currentIndex)
{
if (level != 1)
{
level--;
}
AdjustStackCountToCurrentLevel(stack, level);
UpdateCurrentIndexesForLevels(level);
currentIndex = currentIndexesWithLevels[level];
}
private void AdjustStackCountToCurrentLevel(Stack<int> stack, int currentLevel)
{
while (stack.Count >= currentLevel)
{
if (stack.Count != 0)
stack.Pop();
}
}
public void PrintPermutations()
{
int count = _combinationsList.Where(perm => perm.Count() == _combinationLength).Count();
Console.WriteLine("The number of combinations is " + count);
}
}
We can use recursion for combination/permutation problems involving string or integers.
public static void Main(string[] args)
{
IntegerList = new List<int> { 1, 2, 3, 4 };
PrintAllCombination(default(int), default(int));
}
public static List<int> IntegerList { get; set; }
public static int Length { get { return IntegerList.Count; } }
public static void PrintAllCombination(int position, int prefix)
{
for (int i = position; i < Length; i++)
{
Console.WriteLine(prefix * 10 + IntegerList[i]);
PrintAllCombination(i + 1, prefix * 10 + IntegerList[i]);
}
}
What about
static void Main(string[] args)
{
Combos(new [] { 1, 2, 3 });
}
static void Combos(int[] arr)
{
for (var i = 0; i <= Math.Pow(2, arr.Length); i++)
{
Console.WriteLine();
var j = i;
var idx = 0;
do
{
if ((j & 1) == 1) Console.Write($"{arr[idx]} ");
} while ((j >>= 1) > 0 && ++idx < arr.Length);
}
}
A slightly more generalised version for Linq using C# 7. Here filtering by items that have two elements.
static void Main(string[] args)
{
foreach (var vals in Combos(new[] { "0", "1", "2", "3" }).Where(v => v.Skip(1).Any() && !v.Skip(2).Any()))
Console.WriteLine(string.Join(", ", vals));
}
static IEnumerable<IEnumerable<T>> Combos<T>(T[] arr)
{
IEnumerable<T> DoQuery(long j, long idx)
{
do
{
if ((j & 1) == 1) yield return arr[idx];
} while ((j >>= 1) > 0 && ++idx < arr.Length);
}
for (var i = 0; i < Math.Pow(2, arr.Length); i++)
yield return DoQuery(i, 0);
}
Here is how I did it.
public static List<List<int>> GetCombination(List<int> lst, int index, int count)
{
List<List<int>> combinations = new List<List<int>>();
List<int> comb;
if (count == 0 || index == lst.Count)
{
return null;
}
for (int i = index; i < lst.Count; i++)
{
comb = new List<int>();
comb.Add(lst.ElementAt(i));
combinations.Add(comb);
var rest = GetCombination(lst,i + 1, count - 1);
if (rest != null)
{
foreach (var item in rest)
{
combinations.Add(comb.Union(item).ToList());
}
}
}
return combinations;
}
You call it as :
List<int> lst= new List<int>(new int[]{ 1, 2, 3, 4 });
var combinations = GetCombination(lst, 0, lst.Length)
I just run into a situation where I needed to do this, this is what I came up with:
private static List<string> GetCombinations(List<string> elements)
{
List<string> combinations = new List<string>();
combinations.AddRange(elements);
for (int i = 0; i < elements.Count - 1; i++)
{
combinations = (from combination in combinations
join element in elements on 1 equals 1
let value = string.Join(string.Empty, $"{combination}{element}".OrderBy(c => c).Distinct())
select value).Distinct().ToList();
}
return combinations;
}
It may be not too efficient, and it sure has room for improvement, but gets the job done!
List<string> elements = new List<string> { "1", "2", "3" };
List<string> combinations = GetCombinations(elements);
foreach (string combination in combinations)
{
System.Console.Write(combination);
}
This is an improved version based on the answer from ojlovecd using extension methods:
public static class ListExtensions
{
public static IEnumerable<List<T>> GetCombinations<T>(
this List<T> valuesToCombine)
{
var count = Math.Pow(2, valuesToCombine.Count);
for(var i = 1; i <= count; i++)
{
var itemFlagList = i.ToBinaryString(valuesToCombine.Count())
.Select(x => x == '1').ToList();
yield return GetCombinationByFlagList(valuesToCombine, itemFlagList)
.ToList();
}
}
private static IEnumerable<T> GetCombinationByFlagList<T>(
List<T> valuesToCombine, List<bool> flagList)
{
for (var i = 0; i < valuesToCombine.Count; i++)
{
if (!flagList[i]) continue;
yield return valuesToCombine.ElementAt(i);
}
}
}
public static class IntegerExtensions
{
public static string ToBinaryString(this int value, int length)
{
return Convert.ToString(value, 2).ToString().PadLeft(length, '0');
}
}
Usage:
var numbersList = new List<int>() { 1, 2, 3 };
var combinations = numbersList.GetCombinations();
foreach (var combination in combinations)
{
System.Console.WriteLine(string.Join(",", combination));
}
Output:
3
2
2,3
1
1,3
1,2
1,2,3
The idea is to basically use some flags to keep track of which items were already added to the combination. So in case of 1, 2 & 3, the following binary strings are generated in order to indicate whether an item should be included or excluded:
001, 010, 011, 100, 101, 110 & 111
I'd like to suggest an approach that I find to be quite intuitive and easy to read. (Note: It is slower than the currently accepted solution.)
It is built on the idea that for each integer in the list, we need to extend the so-far-aggregated resulting combination list with
all currently existing combinations, each extended with the given integer
a single "combination" of that integer alone
Here, I am using .Aggregate() with a seed that is an IEnumerable<IEnumerable<int>> containing a single, empty collection entry. That empty entry lets us easily do the two steps above simultaneously. The empty collection entry can be skipped after the resulting combination collection has been aggregated.
It goes like this:
var emptyCollection = Enumerable.Empty<IEnumerable<int>>();
var emptyCombination = Enumerable.Empty<int>();
IEnumerable<int[]> combinations = list
.Aggregate(emptyCollection.Append(emptyCombination),
( acc, next ) => acc.Concat(acc.Select(entry => entry.Append(next))))
.Skip(1) // skip the initial, empty combination
.Select(comb => comb.ToArray());
For each entry in the input integer list { 1, 2, 3 }, the accumulation progresses as follows:
next = 1
{ { } }.Concat({ { }.Append(1) })
{ { } }.Concat({ { 1 } })
{ { }, { 1 } } // acc
next = 2
{ { }, { 1 } }.Concat({ { }.Append(2), { 1 }.Append(2) })
{ { }, { 1 } }.Concat({ { 2 }, { 1, 2 } })
{ { }, { 1 }, { 2 }, { 1, 2 } } // acc
next = 3
{ { }, { 1 }, { 2 }, { 1, 2 } }.Concat({ { }.Append(3), { 1 }.Append(3), { 2 }.Append(3), { 1, 2 }.Append(3) })
{ { }, { 1 }, { 2 }, { 1, 2 } }.Concat({ { 3 }, { 1, 3 }, { 2, 3 }, { 1, 2, 3 } })
{ { }, { 1 }, { 2 }, { 1, 2 }, { 3 }, { 1, 3 }, { 2, 3 }, { 1, 2, 3 } } // acc
Skipping the first (empty) entry, we are left with the following collection:
1
2
1 2
3
1 3
2 3
1 2 3
, which can easily be ordered by collection length and collection entry sum for a clearer overview.
Example fiddle here.
Some of the solutions here are truly ingenious; especially the ones that use bitmaps.
But I found that in practice these algos
aren't easy to modify if a specific range of lengths needed (e.g. all variations of 3 to 5 choices from an input set of 8 elements)
can't handle LARGE input lists (and return empty or singleton results instead of throwing exception); and
can be tricky to debug.
So I decided to write something not as clever as the other people here.
My more basic approach recognises that the set of Variations(1 to maxLength) is simply a UNION of all fixed-length Variations of each length 1 to maxLength:
i.e
Variations(1 to maxLength) = Variations(1) + Variations(2) + ... + Variations(maxLength)
So you can do a "choose K from N" for each required length (for each K in (1, 2, 3, ..., maxLength)) and then just do a Union of these separate results to yield a List of Lists.
This resulting code intends to be easy to understand and to maintain:
/// <summary>
/// Generates ALL variations of length between minLength and maxLength (inclusive)
/// Relies on Combinatorics library to generate each set of Variations
/// Nuget https://www.nuget.org/packages/Combinatorics/
/// Excellent more general references (without this solution):
/// https://www.codeproject.com/Articles/26050/Permutations-Combinations-and-Variations-using-C-G
/// Self-authored solution.
/// </summary>
/// <typeparam name="T">Any type without any constraints.</typeparam>
/// <param name="sourceList">The source list of elements to be combined.</param>
/// <param name="minLength">The minimum length of variation required.</param>
/// <param name="maxLength">The maximum length of variation required.</param>
/// <returns></returns>
public static List<List<T>> GenerateVariations<T>(this IEnumerable<T> sourceList, int minLength, int maxLength)
{
List<List<T>> finalUnion = new();
foreach (int length in Enumerable.Range(minLength, maxLength))
{
Variations<T> variations = new Variations<T>(sourceList, length, GenerateOption.WithoutRepetition);
foreach (var variation in variations)
{
var list = variation.ToList<T>();
finalUnion.Add(list);
}
}
Debug.WriteLine(sourceList.Count() + " source " + typeof(T).Name + " yielded " + finalUnion.Count());
return finalUnion;
}
Happy to receive comments (good and bad). Maybe there's a more succint way to achieve this in LINQ? Maybe the really smart people here can marry their approach with my more basic one?
Please find very very simple solution without recursion and which dont eat RAM.
Unique Combinations
I have a large string I need to parse, and I need to find all the instances of extract"(me,i-have lots. of]punctuation, and store the index of each to a list.
So say this piece of string was in the beginning and middle of the larger string, both of them would be found, and their indexes would be added to the List. and the List would contain 0 and the other index whatever it would be.
I've been playing around, and the string.IndexOf does almost what I'm looking for, and I've written some code - but it's not working and I've been unable to figure out exactly what is wrong:
List<int> inst = new List<int>();
int index = 0;
while (index < source.LastIndexOf("extract\"(me,i-have lots. of]punctuation", 0) + 39)
{
int src = source.IndexOf("extract\"(me,i-have lots. of]punctuation", index);
inst.Add(src);
index = src + 40;
}
inst = The list
source = The large string
Any better ideas?
Here's an example extension method for it:
public static List<int> AllIndexesOf(this string str, string value) {
if (String.IsNullOrEmpty(value))
throw new ArgumentException("the string to find may not be empty", "value");
List<int> indexes = new List<int>();
for (int index = 0;; index += value.Length) {
index = str.IndexOf(value, index);
if (index == -1)
return indexes;
indexes.Add(index);
}
}
If you put this into a static class and import the namespace with using, it appears as a method on any string, and you can just do:
List<int> indexes = "fooStringfooBar".AllIndexesOf("foo");
For more information on extension methods, http://msdn.microsoft.com/en-us/library/bb383977.aspx
Also the same using an iterator:
public static IEnumerable<int> AllIndexesOf(this string str, string value) {
if (String.IsNullOrEmpty(value))
throw new ArgumentException("the string to find may not be empty", "value");
for (int index = 0;; index += value.Length) {
index = str.IndexOf(value, index);
if (index == -1)
break;
yield return index;
}
}
Why don't you use the built in RegEx class:
public static IEnumerable<int> GetAllIndexes(this string source, string matchString)
{
matchString = Regex.Escape(matchString);
foreach (Match match in Regex.Matches(source, matchString))
{
yield return match.Index;
}
}
If you do need to reuse the expression then compile it and cache it somewhere. Change the matchString param to a Regex matchExpression in another overload for the reuse case.
using LINQ
public static IEnumerable<int> IndexOfAll(this string sourceString, string subString)
{
return Regex.Matches(sourceString, subString).Cast<Match>().Select(m => m.Index);
}
Polished version + case ignoring support:
public static int[] AllIndexesOf(string str, string substr, bool ignoreCase = false)
{
if (string.IsNullOrWhiteSpace(str) ||
string.IsNullOrWhiteSpace(substr))
{
throw new ArgumentException("String or substring is not specified.");
}
var indexes = new List<int>();
int index = 0;
while ((index = str.IndexOf(substr, index, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal)) != -1)
{
indexes.Add(index++);
}
return indexes.ToArray();
}
It could be done in efficient time complexity using KMP algorithm in O(N + M) where N is the length of text and M is the length of the pattern.
This is the implementation and usage:
static class StringExtensions
{
public static IEnumerable<int> AllIndicesOf(this string text, string pattern)
{
if (string.IsNullOrEmpty(pattern))
{
throw new ArgumentNullException(nameof(pattern));
}
return Kmp(text, pattern);
}
private static IEnumerable<int> Kmp(string text, string pattern)
{
int M = pattern.Length;
int N = text.Length;
int[] lps = LongestPrefixSuffix(pattern);
int i = 0, j = 0;
while (i < N)
{
if (pattern[j] == text[i])
{
j++;
i++;
}
if (j == M)
{
yield return i - j;
j = lps[j - 1];
}
else if (i < N && pattern[j] != text[i])
{
if (j != 0)
{
j = lps[j - 1];
}
else
{
i++;
}
}
}
}
private static int[] LongestPrefixSuffix(string pattern)
{
int[] lps = new int[pattern.Length];
int length = 0;
int i = 1;
while (i < pattern.Length)
{
if (pattern[i] == pattern[length])
{
length++;
lps[i] = length;
i++;
}
else
{
if (length != 0)
{
length = lps[length - 1];
}
else
{
lps[i] = length;
i++;
}
}
}
return lps;
}
and this is an example of how to use it:
static void Main(string[] args)
{
string text = "this is a test";
string pattern = "is";
foreach (var index in text.AllIndicesOf(pattern))
{
Console.WriteLine(index); // 2 5
}
}
Without Regex, using string comparison type:
string search = "123aa456AA789bb9991AACAA";
string pattern = "AA";
Enumerable.Range(0, search.Length)
.Select(index => { return new { Index = index, Length = (index + pattern.Length) > search.Length ? search.Length - index : pattern.Length }; })
.Where(searchbit => searchbit.Length == pattern.Length && pattern.Equals(search.Substring(searchbit.Index, searchbit.Length),StringComparison.OrdinalIgnoreCase))
.Select(searchbit => searchbit.Index)
This returns {3,8,19,22}. Empty pattern would match all positions.
For multiple patterns:
string search = "123aa456AA789bb9991AACAA";
string[] patterns = new string[] { "aa", "99" };
patterns.SelectMany(pattern => Enumerable.Range(0, search.Length)
.Select(index => { return new { Index = index, Length = (index + pattern.Length) > search.Length ? search.Length - index : pattern.Length }; })
.Where(searchbit => searchbit.Length == pattern.Length && pattern.Equals(search.Substring(searchbit.Index, searchbit.Length), StringComparison.OrdinalIgnoreCase))
.Select(searchbit => searchbit.Index))
This returns {3, 8, 19, 22, 15, 16}
I noticed that at least two proposed solutions don't handle overlapping search hits. I didn't check the one marked with the green checkmark. Here is one that handles overlapping search hits:
public static List<int> GetPositions(this string source, string searchString)
{
List<int> ret = new List<int>();
int len = searchString.Length;
int start = -1;
while (true)
{
start = source.IndexOf(searchString, start +1);
if (start == -1)
{
break;
}
else
{
ret.Add(start);
}
}
return ret;
}
public List<int> GetPositions(string source, string searchString)
{
List<int> ret = new List<int>();
int len = searchString.Length;
int start = -len;
while (true)
{
start = source.IndexOf(searchString, start + len);
if (start == -1)
{
break;
}
else
{
ret.Add(start);
}
}
return ret;
}
Call it like this:
List<int> list = GetPositions("bob is a chowder head bob bob sldfjl", "bob");
// list will contain 0, 22, 26
Hi nice answer by #Matti Virkkunen
public static List<int> AllIndexesOf(this string str, string value) {
if (String.IsNullOrEmpty(value))
throw new ArgumentException("the string to find may not be empty", "value");
List<int> indexes = new List<int>();
for (int index = 0;; index += value.Length) {
index = str.IndexOf(value, index);
if (index == -1)
return indexes;
indexes.Add(index);
index--;
}
}
But this covers tests cases like AOOAOOA
where substring
are AOOA and AOOA
Output 0 and 3
#csam is correct in theory, although his code will not complie and can be refractored to
public static IEnumerable<int> IndexOfAll(this string sourceString, string matchString)
{
matchString = Regex.Escape(matchString);
return from Match match in Regex.Matches(sourceString, matchString) select match.Index;
}
public static Dictionary<string, IEnumerable<int>> GetWordsPositions(this string input, string[] Susbtrings)
{
Dictionary<string, IEnumerable<int>> WordsPositions = new Dictionary<string, IEnumerable<int>>();
IEnumerable<int> IndexOfAll = null;
foreach (string st in Susbtrings)
{
IndexOfAll = Regex.Matches(input, st).Cast<Match>().Select(m => m.Index);
WordsPositions.Add(st, IndexOfAll);
}
return WordsPositions;
}
Based on the code I've used for finding multiple instances of a string within a larger string, your code would look like:
List<int> inst = new List<int>();
int index = 0;
while (index >=0)
{
index = source.IndexOf("extract\"(me,i-have lots. of]punctuation", index);
inst.Add(index);
index++;
}
I found this example and incorporated it into a function:
public static int solution1(int A, int B)
{
// Check if A and B are in [0...999,999,999]
if ( (A >= 0 && A <= 999999999) && (B >= 0 && B <= 999999999))
{
if (A == 0 && B == 0)
{
return 0;
}
// Make sure A < B
if (A < B)
{
// Convert A and B to strings
string a = A.ToString();
string b = B.ToString();
int index = 0;
// See if A is a substring of B
if (b.Contains(a))
{
// Find index where A is
if (b.IndexOf(a) != -1)
{
while ((index = b.IndexOf(a, index)) != -1)
{
Console.WriteLine(A + " found at position " + index);
index++;
}
Console.ReadLine();
return b.IndexOf(a);
}
else
return -1;
}
else
{
Console.WriteLine(A + " is not in " + B + ".");
Console.ReadLine();
return -1;
}
}
else
{
Console.WriteLine(A + " must be less than " + B + ".");
// Console.ReadLine();
return -1;
}
}
else
{
Console.WriteLine("A or B is out of range.");
//Console.ReadLine();
return -1;
}
}
static void Main(string[] args)
{
int A = 53, B = 1953786;
int C = 78, D = 195378678;
int E = 57, F = 153786;
solution1(A, B);
solution1(C, D);
solution1(E, F);
Console.WriteLine();
}
Returns:
53 found at position 2
78 found at position 4
78 found at position 7
57 is not in 153786
How is this alternative implementation?
public static class MyExtensions
{
public static int HowMany(this string str, char needle)
{
int counter = 0;
int nextIndex = 0;
for (; nextIndex != -1; )
{
nextIndex = str.IndexOf(needle, nextIndex);
if (nextIndex != -1)
{
counter++;
//step over to the next char
nextIndex++;
}
}
return counter;
}
}
you can use linq to select and enumerate all elements, then find by any string:
I've created a class:
class Pontos
{
//index on string
public int Pos { get; set; }
//caractere
public string Caractere { get; set; }
}
And use like this:
int count = 0;
var pontos = texto.Select(y => new Pontos { Pos = count++, Caractere = y.ToString() }).Where(x=>x.Caractere == ".").ToList();
then:
input string:
output list:
PS: SeForNumero is another field of my class, I need this for my own purposes, but is not necessary to this use.