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'm creating a program which requires to check every possible permutation. let's say we have 1,2,3 the program will work just fine and show me all the possible ones : 1,3,2 2,1,3 2,3,1 3,1,2 and 3,2,1 however i also want it to be able to try such combinations
1,1,1
2,2,2
1,2,2
3,3,2
i.e include absolutely every possible combination.. Here's my code :
public static bool NextPermutation<T>(T[] elements) where T : IComparable<T>
{
// More efficient to have a variable instead of accessing a property
var count = elements.Length;
// Indicates whether this is the last lexicographic permutation
var done = true;
// Go through the array from last to first
for (var i = count - 1; i > 0; i--)
{
var curr = elements[i];
// Check if the current element is less than the one before it
if (curr.CompareTo(elements[i - 1]) < 0)
{
continue;
}
// An element bigger than the one before it has been found,
// so this isn't the last lexicographic permutation.
done = false;
// Save the previous (bigger) element in a variable for more efficiency.
var prev = elements[i - 1];
// Have a variable to hold the index of the element to swap
// with the previous element (the to-swap element would be
// the smallest element that comes after the previous element
// and is bigger than the previous element), initializing it
// as the current index of the current item (curr).
var currIndex = i;
// Go through the array from the element after the current one to last
for (var j = i + 1; j < count; j++)
{
// Save into variable for more efficiency
var tmp = elements[j];
// Check if tmp suits the "next swap" conditions:
// Smallest, but bigger than the "prev" element
if (tmp.CompareTo(curr) < 0 && tmp.CompareTo(prev) > 0)
{
curr = tmp;
currIndex = j;
}
}
// Swap the "prev" with the new "curr" (the swap-with element)
elements[currIndex] = prev;
elements[i - 1] = curr;
// Reverse the order of the tail, in order to reset it's lexicographic order
for (var j = count - 1; j > i; j--, i++)
{
var tmp = elements[j];
elements[j] = elements[i];
elements[i] = tmp;
}
// Break since we have got the next permutation
// The reason to have all the logic inside the loop is
// to prevent the need of an extra variable indicating "i" when
// the next needed swap is found (moving "i" outside the loop is a
// bad practice, and isn't very readable, so I preferred not doing
// that as well).
break;
}
// Return whether this has been the last lexicographic permutation.
return done;
}
This is a simple example of how i use it
var arr = new[] {0, 1, 2,};
var conditions = new[] {true, false, true};
int count = 0;
while (!NextPermutation(arr))
{
List<bool> tempConditions = new List<bool>();
for (int i = 0; i < arr.Length; i++)
{
tempConditions.Add(conditions[arr[i]]);
Console.Write(tempConditions[i] + " ");
}
count++;
Console.WriteLine();
}
Console.WriteLine("count : {0}", count);
You can do this with a method that returns IEnumerable<IEnumerable<T>> like so:
using System;
using System.Collections.Generic;
using System.Linq;
namespace Demo
{
public static class Program
{
public static void Main()
{
string[] test = {"A", "B", "C", "D"};
foreach (var perm in PermuteWithRepeats(test))
Console.WriteLine(string.Join(" ", perm));
}
public static IEnumerable<IEnumerable<T>> PermuteWithRepeats<T>(IEnumerable<T> sequence)
{
return permuteWithRepeats(sequence, sequence.Count());
}
private static IEnumerable<IEnumerable<T>> permuteWithRepeats<T>(IEnumerable<T> sequence, int count)
{
if (count == 0)
{
yield return Enumerable.Empty<T>();
}
else
{
foreach (T startingElement in sequence)
{
IEnumerable<T> remainingItems = sequence;
foreach (IEnumerable<T> permutationOfRemainder in permuteWithRepeats(remainingItems, count - 1))
yield return new[]{startingElement}.Concat(permutationOfRemainder);
}
}
}
}
}
1,1,2 2,2,2 and such aren't permutations - they are variations. There will be count ^ count of them
You can generate them like this:
// you can do precise powering if needed
double number_of_variations = Math.Pow(count, count);
T[] result = new T[count];
for (int i = 0; i < number_of_variations; ++i) {
int x = i;
for (int j = 0; j < count; ++j) {
result[j] = elements[x % count];
x /= count;
}
// do something with one of results
}
I have a List containing values 10, 20, 30, 50,30
i would like to add all possible sum of the values present in the list that is:
10+20 = 30
10+30 = 40
10+50 = 60
20+30 = 50
10+20+30+50+30
the list i declared is something like this:
List list = new List();
and values(i.e 10, 20, 30, 50, 30) were added using a for loop.
Done so far:
List<int> list = new List<int>();
list.Add(3);
list.Add(7);
list.Add(8);
list.Add(1);
var length = list.Count();
for (int i = 0; i < length; i++)
{
var sum = 0;
sum = sum + list[i];
for (int j = i + 1; j < length; j++)
{
sum = sum + list[j];
list.Add(list[i] + list[j]);
}
list.Add(sum);
}
This works for me:
Func<IEnumerable<int>, IEnumerable<int>> getAllSelectionSums = null;
getAllSelectionSums = xs =>
{
if (!xs.Any())
{
return new [] { 0 };
}
else
{
return
from h in xs.Take(1).Concat(new [] { 0 })
from t in getAllSelectionSums(xs.Skip(1))
select h + t;
}
};
So, given var source = new [] { 3, 7, 8, 1 }; as the input I get the following result:
This is typically done with two for loops if you want only 2 elements. However, if you wanted to pick all combinations from 1 to all elements, you are looking for the power set.
I will answer it for just picking 2
List<int> sums = new List<int>();
for(int first = list.Length - 1; first >= 1; first--)
{
for(int second = first - 1; second >= 0; second--)
{
sums.Add(list[first] + list[second]);
}
}
You should also bracket this to make sure your list has at least 2 items in it...
Edit:
Since you've updated your question to show your implementation, I'll include code to generate power sets
public IEnumerable<IEnumerable<int>> PowerSet(IEnumerable<int> initialSet)
{
foreach (IEnumerable<int> set in PowerSetRecursive(initialSet, initialSet.Count() - 1))
{
yield return set;
}
}
private IEnumerable<IEnumerable<int>> PowerSetRecursive(IEnumerable<int> initialSet, int index)
{
if (index == 0)
{
yield return new int[] { };
yield return new int[] { initialSet.ElementAt(index) };
}
else
{
foreach (IEnumerable<int> set in PowerSetRecursive(initialSet, index - 1))
{
yield return new HashSet<int>(set);
yield return new HashSet<int>(set) { initialSet.ElementAt(index) };
}
}
}
You would then loop like this
foreach (IEnumerable<int> set in PowerSet(new int[] { 1, 2, 3, 4 }))
{
Console.WriteLine(set.Sum());
}
I have a list of Offers, from which I want to create "chains" (e.g. permutations) with limited chain lengths.
I've gotten as far as creating the permutations using the Kw.Combinatorics project.
However, the default behavior creates permutations in the length of the list count. I'm not sure how to limit the chain lengths to 'n'.
Here's my current code:
private static List<List<Offers>> GetPerms(List<Offers> list, int chainLength)
{
List<List<Offers>> response = new List<List<Offers>>();
foreach (var row in new Permutation(list.Count).GetRows())
{
List<Offers> innerList = new List<Offers>();
foreach (var mix in Permutation.Permute(row, list))
{
innerList.Add(mix);
}
response.Add(innerList);
innerList = new List<Offers>();
}
return response;
}
Implemented by:
List<List<AdServer.Offers>> lst = GetPerms(offers, 2);
I'm not locked in KWCombinatorics if someone has a better solution to offer.
Here's another implementation which I think should be faster than the accepted answer (and it's definitely less code).
public static IEnumerable<IEnumerable<T>> GetVariationsWithoutDuplicates<T>(IList<T> items, int length)
{
if (length == 0 || !items.Any()) return new List<List<T>> { new List<T>() };
return from item in items.Distinct()
from permutation in GetVariationsWithoutDuplicates(items.Where(i => !EqualityComparer<T>.Default.Equals(i, item)).ToList(), length - 1)
select Prepend(item, permutation);
}
public static IEnumerable<IEnumerable<T>> GetVariations<T>(IList<T> items, int length)
{
if (length == 0 || !items.Any()) return new List<List<T>> { new List<T>() };
return from item in items
from permutation in GetVariations(Remove(item, items).ToList(), length - 1)
select Prepend(item, permutation);
}
public static IEnumerable<T> Prepend<T>(T first, IEnumerable<T> rest)
{
yield return first;
foreach (var item in rest) yield return item;
}
public static IEnumerable<T> Remove<T>(T item, IEnumerable<T> from)
{
var isRemoved = false;
foreach (var i in from)
{
if (!EqualityComparer<T>.Default.Equals(item, i) || isRemoved) yield return i;
else isRemoved = true;
}
}
On my 3.1 GHz Core 2 Duo, I tested with this:
public static void Test(Func<IList<int>, int, IEnumerable<IEnumerable<int>>> getVariations)
{
var max = 11;
var timer = System.Diagnostics.Stopwatch.StartNew();
for (int i = 1; i < max; ++i)
for (int j = 1; j < i; ++j)
getVariations(MakeList(i), j).Count();
timer.Stop();
Console.WriteLine("{0,40}{1} ms", getVariations.Method.Name, timer.ElapsedMilliseconds);
}
// Make a list that repeats to guarantee we have duplicates
public static IList<int> MakeList(int size)
{
return Enumerable.Range(0, size/2).Concat(Enumerable.Range(0, size - size/2)).ToList();
}
Unoptimized
GetVariations 11894 ms
GetVariationsWithoutDuplicates 9 ms
OtherAnswerGetVariations 22485 ms
OtherAnswerGetVariationsWithDuplicates 243415 ms
With compiler optimizations
GetVariations 9667 ms
GetVariationsWithoutDuplicates 8 ms
OtherAnswerGetVariations 19739 ms
OtherAnswerGetVariationsWithDuplicates 228802 ms
You're not looking for a permutation, but for a variation. Here is a possible algorithm. I prefer iterator methods for functions that can potentially return very many elements. This way, the caller can decide if he really needs all elements:
IEnumerable<IList<T>> GetVariations<T>(IList<T> offers, int length)
{
var startIndices = new int[length];
var variationElements = new HashSet<T>(); //for duplicate detection
while (startIndices[0] < offers.Count)
{
var variation = new List<T>(length);
var valid = true;
for (int i = 0; i < length; ++i)
{
var element = offers[startIndices[i]];
if (variationElements.Contains(element))
{
valid = false;
break;
}
variation.Add(element);
variationElements.Add(element);
}
if (valid)
yield return variation;
//Count up the indices
startIndices[length - 1]++;
for (int i = length - 1; i > 0; --i)
{
if (startIndices[i] >= offers.Count)
{
startIndices[i] = 0;
startIndices[i - 1]++;
}
else
break;
}
variationElements.Clear();
}
}
The idea for this algorithm is to use a number in offers.Count base. For three offers, all digits are in the range 0-2. We then basically increment this number step by step and return the offers that reside at the specified indices. If you want to allow duplicates, you can remove the check and the HashSet<T>.
Update
Here is an optimized variant that does the duplicate check on the index level. In my tests it is a lot faster than the previous variant:
IEnumerable<IList<T>> GetVariations<T>(IList<T> offers, int length)
{
var startIndices = new int[length];
for (int i = 0; i < length; ++i)
startIndices[i] = i;
var indices = new HashSet<int>(); // for duplicate check
while (startIndices[0] < offers.Count)
{
var variation = new List<T>(length);
for (int i = 0; i < length; ++i)
{
variation.Add(offers[startIndices[i]]);
}
yield return variation;
//Count up the indices
AddOne(startIndices, length - 1, offers.Count - 1);
//duplicate check
var check = true;
while (check)
{
indices.Clear();
for (int i = 0; i <= length; ++i)
{
if (i == length)
{
check = false;
break;
}
if (indices.Contains(startIndices[i]))
{
var unchangedUpTo = AddOne(startIndices, i, offers.Count - 1);
indices.Clear();
for (int j = 0; j <= unchangedUpTo; ++j )
{
indices.Add(startIndices[j]);
}
int nextIndex = 0;
for(int j = unchangedUpTo + 1; j < length; ++j)
{
while (indices.Contains(nextIndex))
nextIndex++;
startIndices[j] = nextIndex++;
}
break;
}
indices.Add(startIndices[i]);
}
}
}
}
int AddOne(int[] indices, int position, int maxElement)
{
//returns the index of the last element that has not been changed
indices[position]++;
for (int i = position; i > 0; --i)
{
if (indices[i] > maxElement)
{
indices[i] = 0;
indices[i - 1]++;
}
else
return i;
}
return 0;
}
If I got you correct here is what you need
this will create permutations based on the specified chain limit
public static List<List<T>> GetPerms<T>(List<T> list, int chainLimit)
{
if (list.Count() == 1)
return new List<List<T>> { list };
return list
.Select((outer, outerIndex) =>
GetPerms(list.Where((inner, innerIndex) => innerIndex != outerIndex).ToList(), chainLimit)
.Select(perms => (new List<T> { outer }).Union(perms).Take(chainLimit)))
.SelectMany<IEnumerable<IEnumerable<T>>, List<T>>(sub => sub.Select<IEnumerable<T>, List<T>>(s => s.ToList()))
.Distinct(new PermComparer<T>()).ToList();
}
class PermComparer<T> : IEqualityComparer<List<T>>
{
public bool Equals(List<T> x, List<T> y)
{
return x.SequenceEqual(y);
}
public int GetHashCode(List<T> obj)
{
return (int)obj.Average(o => o.GetHashCode());
}
}
and you'll call it like this
List<List<AdServer.Offers>> lst = GetPerms<AdServer.Offers>(offers, 2);
I made this function is pretty generic so you may use it for other purpose too
eg
List<string> list = new List<string>(new[] { "apple", "banana", "orange", "cherry" });
List<List<string>> perms = GetPerms<string>(list, 2);
result
I've got a two-dimensional array,
string[,] table = {
{ "aa", "aaa" },
{ "bb", "bbb" }
};
And I'd like to foreach through it like this,
foreach (string[] row in table)
{
Console.WriteLine(row[0] + " " + row[1]);
}
But, I get the error:
Can't convert type string to string[]
Is there a way I can achieve what I want, i.e. iterate through the first dimension of the array with the iterator variable returning me the one-dimensional array for that row?
Multidimensional arrays aren't enumerable. Just iterate the good old-fashioned way:
for (int i = 0; i < table.GetLength(0); i++)
{
Console.WriteLine(table[i, 0] + " " + table[i, 1]);
}
As others have suggested, you could use nested for-loops or redeclare your multidimensional array as a jagged one.
However, I think it's worth pointing out that multidimensional arrays are enumerable, just not in the way that you want. For example:
string[,] table = {
{ "aa", "aaa" },
{ "bb", "bbb" }
};
foreach (string s in table)
{
Console.WriteLine(s);
}
/* Output is:
aa
aaa
bb
bbb
*/
If you define your array like this:
string[][] table = new string[][] {
new string[] { "aa", "aaa" },
new string[]{ "bb", "bbb" }
};
Then you can use a foreach loop on it.
UPDATE: I had some time on my hands, so ... I went ahead and fleshed out this idea. See below for the code.
Here's a bit of a crazy answer:
You could do what you're looking for -- essentially treat a two-dimensional array as a table with rows -- by writing a static method (perhaps an extension method) that takes a T[,] and returns an IEnumerable<T[]>. This would require copying each "row" of the underlying table into a new array, though.
A perhaps better (though more involved) approach would be to actually write a class that implements IList<T> as a wrapper around a single "row" of a two-dimensional array (you would probably set IsReadOnly to true and just implement the getter for the this[int] property and probably Count and GetEnumerator; everything else could throw a NotSupportedException). Then your static/extension method could return an IEnumerable<IList<T>> and provide deferred execution.
That way you could write code pretty much like what you have:
foreach (IList<string> row in table.GetRows()) // or something
{
Console.WriteLine(row[0] + " " + row[1]);
}
Just a thought.
Implementation suggestion:
public static class ArrayTableHelper {
public static IEnumerable<IList<T>> GetRows<T>(this T[,] table) {
for (int i = 0; i < table.GetLength(0); ++i)
yield return new ArrayTableRow<T>(table, i);
}
private class ArrayTableRow<T> : IList<T> {
private readonly T[,] _table;
private readonly int _count;
private readonly int _rowIndex;
public ArrayTableRow(T[,] table, int rowIndex) {
if (table == null)
throw new ArgumentNullException("table");
if (rowIndex < 0 || rowIndex >= table.GetLength(0))
throw new ArgumentOutOfRangeException("rowIndex");
_table = table;
_count = _table.GetLength(1);
_rowIndex = rowIndex;
}
// I didn't implement the setter below,
// but you easily COULD (and then set IsReadOnly to false?)
public T this[int index] {
get { return _table[_rowIndex, index]; }
set { throw new NotImplementedException(); }
}
public int Count {
get { return _count; }
}
bool ICollection<T>.IsReadOnly {
get { return true; }
}
public IEnumerator<T> GetEnumerator() {
for (int i = 0; i < _count; ++i)
yield return this[i];
}
// omitted remaining IList<T> members for brevity;
// you actually could implement IndexOf, Contains, etc.
// quite easily, though
}
}
...now I think I should give StackOverflow a break for the rest of the day ;)
It depends on how you define your multi-dimensional array. Here are two options:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
// First
string[,] arr1 = {
{ "aa", "aaa" },
{ "bb", "bbb" }
};
// Second
string[][] arr2 = new[] {
new[] { "aa", "aaa" },
new[] { "bb", "bbb" }
};
// Iterate through first
for (int x = 0; x <= arr1.GetUpperBound(0); x++)
for (int y = 0; y <= arr1.GetUpperBound(1); y++)
Console.Write(arr1[x, y] + "; ");
Console.WriteLine(Environment.NewLine);
// Iterate through second second
foreach (string[] entry in arr2)
foreach (string element in entry)
Console.Write(element + "; ");
Console.WriteLine(Environment.NewLine);
Console.WriteLine("Press any key to finish");
Console.ReadKey();
}
}
}
Here's a simple extension method that returns each row as an IEnumerable<T>. This has the advantage of not using any extra memory:
public static class Array2dExt
{
public static IEnumerable<IEnumerable<T>> Rows<T>(this T[,] array)
{
for (int r = array.GetLowerBound(0); r <= array.GetUpperBound(0); ++r)
yield return row(array, r);
}
static IEnumerable<T> row<T>(T[,] array, int r)
{
for (int c = array.GetLowerBound(1); c <= array.GetUpperBound(1); ++c)
yield return array[r, c];
}
}
Sample usage:
static void Main()
{
string[,] siblings = { { "Mike", "Amy" }, { "Mary", "Albert" }, {"Fred", "Harry"} };
foreach (var row in siblings.Rows())
Console.WriteLine("{" + string.Join(", ", row) + "}");
}
string[][] table = { ... };
string[][] languages = new string[2][];
languages[0] = new string[2];
languages[1] = new string[3];
// inserting data into double dimensional arrays.
for (int i = 0; i < 2; i++)
{
languages[0][i] = "Jagged"+i.ToString();
}
for (int j = 0; j < 3; j++)
{
languages[1][j] = "Jag"+j.ToString();
}
// doing foreach through 2 dimensional arrays.
foreach (string[] s in languages)
{
foreach (string a in s)
{
Console.WriteLine(a);
}
}
Using LINQ you can do it like this:
var table_enum = table
// Convert to IEnumerable<string>
.OfType<string>()
// Create anonymous type where Index1 and Index2
// reflect the indices of the 2-dim. array
.Select((_string, _index) => new {
Index1 = (_index / 2),
Index2 = (_index % 2), // ← I added this only for completeness
Value = _string
})
// Group by Index1, which generates IEnmurable<string> for all Index1 values
.GroupBy(v => v.Index1)
// Convert all Groups of anonymous type to String-Arrays
.Select(group => group.Select(v => v.Value).ToArray());
// Now you can use the foreach-Loop as you planned
foreach(string[] str_arr in table_enum) {
// …
}
This way it is also possible to use the foreach for looping through the columns instead of the rows by using Index2 in the GroupBy instead of Index 1. If you don't know the dimension of your array then you have to use the GetLength() method to determine the dimension and use that value in the quotient.
I'm not a big fan of this method because of the memory usage involved, but if you use the arrays it produces, it isn't such a waste.
public static void ForEachRow<T>(this T[,] list, Action<int, T[]> action)
{
var len = list.GetLength(0);
var sub = list.GetLength(1);
T[] e;
int i, j;
for (i = 0; i < len; i++)
{
e = new T[sub];
for (j = 0; j < sub; j++)
{
e[j] = list[i, j];
}
action(i, e);
}
}
Implementation:
var list = new[,]{0x0, 0x1, 0x2, 0x4, 0x8};
list.ForEachRow((i, row) =>
{
for (var j = 0; j < row.Length; j++)
{
Console.WriteLine("[{0},{1}]: {2}", i, j, row[j]);
}
});
The other solution I found is less memory intensive, but will use more CPU, especially when the dimensions of the arrays' entries are larger.
public static void ForEachRow<T>(this T[,] list, Action<int, IEnumerable<T>> action)
{
var len = list.GetLength(0);
var sub = list.GetLength(1);
int i, j;
IEnumerable<T> e;
for (i = 0; i < len; i++)
{
e = Enumerable.Empty<T>();
for (j = 0; j < sub; j++)
{
e = e.Concat(AsEnumerable(list[i, j]));
}
action(i, e);
}
}
private static IEnumerable<T> AsEnumerable<T>(T add)
{
yield return add;
}
Implementation:
var list = new[,]{0x0, 0x1, 0x2, 0x4, 0x8};
list.ForEachRow((i, row) =>
{
var j = 0;
forrach (var o in row)
{
Console.WriteLine("[{0},{1}]: {2}", i, j, o);
++j;
}
});
As a whole, I find the first option to be more intuitive, especially if you want to access the produced array by its indexer.
At the end of the day, this is all just eye candy, neither methods should really be used in favour of directly accessing the source array;
for (var i = 0; i < list.GetLength(0); i++)
{
foreach (var j = 0; j < list.GetLength(1); j++)
{
Console.WriteLine("[{0},{1}]: {2}", i, j, list[i, j]);
}
}
Remember that a multi-dimensional array is like a table. You don't have an x element and a y element for each entry; you have a string at (for instance) table[1,2].
So, each entry is still only one string (in your example), it's just an entry at a specific x/y value. So, to get both entries at table[1, x], you'd do a nested for loop. Something like the following (not tested, but should be close)
for (int x = 0; x < table.Length; x++)
{
for (int y = 0; y < table.Length; y += 2)
{
Console.WriteLine("{0} {1}", table[x, y], table[x, y + 1]);
}
}
I try this. I hope to help. It work with
static void Main()
{
string[,] matrix = {
{ "aa", "aaa" },
{ "bb", "bbb" }
};
int index = 0;
foreach (string element in matrix)
{
if (index < matrix.GetLength(1))
{
Console.Write(element);
if (index < (matrix.GetLength(1) - 1))
{
Console.Write(" ");
}
index++;
}
if (index == matrix.GetLength(1))
{
Console.Write("\n");
index = 0;
}
}