so I am super new to c# and to programming in general. Anyways I am trying to create a function that creates and returns a list of multiples of a number. For example, MultiplesOf(3,5), where the 3 is the starting number and 5 is the number of multiples, would result in {3, 6, 9, 12, 15}. This is what I have so far:
private static double[] MultiplesOf(double number, int length)
{
List<int> results = new List<int>();
// TODO Problem 1 Start
for (int i = 1; i <= length; i++)
{
if ( i % number == 0)
results.Add(i);
}
return results;
}
Any suggestions would be greatly appricated!
Instead of dividing the length by the current number i, why not just add the number to the previous number? Multiplying something is nothing different than just adding it again and again, is it? So the term 3 * 3 is the same like 3 + 3 + 3.
List<int> results = new List<int>();
// TODO Problem 1 Start
for ( int i = 1; i <= length; i++)
{
number += number;
result.Add(number);
}
return results;
Apart from this your method should return List<int>, instead of double[].
you just need to multiply the length[i] by the number you want to find the multiples on.
public List<int> MultiplesOf(int number, int length)
{
List<int> results = new List<int>();
for ( int i = 1; i <= length; i++)
{
results.Add(i * number);
}
return results;
}
}
for ( int i = 1; i <= length; i++)
{
results.Add(i*number);
}
return results;
If you want to keep the return type of the method to array of double. please try this way
private static double[] MultiplesOf(double number, int length)
{
//return type of the method is array of double data type, so we are declaring the return variable with double[] datatype.
double[] results = new double[length];
for (int i = 1; i <= length; i++)
{
//instead of mod operation, you need to multiply the number and add to array.
results[i-1] = (number*i);
}
return results;
}
You can modify your function like below:
public static List<int> MultiplesOf(int number, int length)
{
List<int> results = new List<int>();
// TODO Problem 1 Start
for (int i = 1; results.Count <= length - 1; i++)
{
if (i % number == 0)
results.Add(i);
}
return results;
}
This for loop above makes length times control. If you want a more performance way you can modify your function like this:
public static List<int> MultiplesOf(int number, int length)
{
List<int> results = new List<int>();
// TODO Problem 1 Start
for (int i = 1; results.Count <= length - 1; i++)
{
results.Add(i * number);
}
return results;
}
For see the output
var x = MultiplesOf(3,5);
foreach (var item in x)
{
Console.Write($"{item}, ");
}
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 want to sort only odd numbers without moving even numbers. For example, if my input is:
[5, 3, 2, 8, 1, 4]
The expected result is:
[1, 3, 2, 8, 5, 4]
I am new to C# and I came across a challenge on the Internet that has me perplexed. I have tried for hours and I would like to learn this concept in
The challenge states:
You have an array of numbers. Your task is to sort ascending odd numbers but even numbers must be on their places. Zero isn't an odd number and you don't need to move it. If you have an empty array, you need to return it.
Here is my code so far, please take it easy on me I am in the beginning stages of programming.
public static int[] SortArray(int[] array)
{
var dict = new Dictionary<int, int>();
var dict2 = new Dictionary<int, int>();
for (int i = 0; i < array.Length; i++)
{
int j =0;
if (array[i] % 2 != 0)
{
dict.Add(array[i], i+1);
}
else
{
dict2.Add(array[i], i+1);
}
}
var result = dict.OrderBy(x => x.Key);
Dictionary<int, int> resultDic = result.Union(dict2)
.GroupBy(x => x.Key).ToDictionary(o => o.Key, o => o.Key);
}
public static void Main()
{
SortArray(new int[] { 5, 3, 2, 8, 1, 4});
}
Check this code. Explanations added as comments
public static int[] SortArray(int[] array)
{
//temp variable for holding larger value for switching
int temp = 0;
for (int i = 0; i < array.Length; i++)
{
//If the value is 'even' continue with outer loop
if(array[i] % 2 == 0)
continue;
//Inner loop to compare array values
for(int j = (i + 1); j < array.Length; j++)
{
//If this value is not even do comparison
if(array[j] % 2 != 0)
{
//If the left value is greater than the right value
//swap them
if(array[i] > array[j])
{
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
}
return array;
}
public static void Main()
{
SortArray(new int[] { 5, 3, 2, 8, 1, 4});
}
You can do this with linq by indexing the numbers before you start:
var nums = new[] { 5, 3, 2, 8, 1, 4 };
var indexedNums = nums.Select((num, idx) => new { num, idx }).ToList();
Then sorting these indexed numbers into evens and odds:
var evens = indexedNums.Where(x => x.num % 2 == 0);
var odds = indexedNums.Where(x => x.num % 2 == 1);
Sorting the odd (indexed) numbers by their value:
var sortedOdds = odds.OrderBy(x => x.num); //sort the odd numbers by their value
Zipping this sequence with the odds sequence (which is sorted by index), taking the number from sortedOdds and the index from odds
var reindexedOdds = sortedOdds.Zip(odds, (o1, o2) => new { o1.num, o2.idx });
...and throwing these reindexedOdds into a sequence with the indexed evens from above, sorting by index and then selecting out the number.
var endSequence = evens.Concat(reindexedOdds).OrderBy(x => x.idx).Select(x => x.num);
While the other solutions are formally correct, most of them are not efficient, being with O(n^2) time complexity.
Another (and more time efficient) approach should imply the use of two lists: the first will contain the indexes of odd numbers, and the second will store the sorted odd numbers.
public static int[] SortArray(int[] array)
{
var sortedOdds = new List<int>(array.Length);
var oddsIndexes = new List<int>(array.Length);
var newArray = new int[array.Length];
for(var i = 0; i < array.Length; i++) // O(n)
{
var value = array[i];
if(value % 2 == 1)
{
sortedOdds.Add(value);
oddsIndexes.Add(i);
} else
{
newArray[i] = value;
}
}
sortedOdds.Sort(); // average complexity O(n log n)
for(var j = 0; j < sortedOdds.Count; j++) // O(n)
{
var value = sortedOdds[j];
var index = oddsIndexes[j];
newArray[index] = value;
}
return newArray;
}
This will reduce the complexity to an average of O(n log n) time.
This question already has answers here:
How to generate all subsets of a given size?
(5 answers)
Closed 6 years ago.
Looking for an efficient way to determine all unique subsets of a list of integers.
Say I have a List of integers containing 340 integers. I want a List of all possible subsets (of 5 elements each). All supplied integers will be unique, and the result should not duplicate any element in it's subset. An example given an input of 1,2,3,4,5,6,7,8,9 I am looking for an output of
1,2,3,4,5
1,2,3,4,6
1,2,3,4,7
1,2,3,4,8
1,2,3,4,9
1,2,3,5,6
1,2,3,5,7
...
I must do this in CSharp. can this be done in LINQ?
I have answered a several combinatorial questions, and everywhere I use a variation of a non recursive allocation free algorithm. For this case, it looks like this:
public static class Algorithms
{
public static IEnumerable<T[]> GetCombinations<T>(this T[] input, int N)
{
var result = new T[N];
var indices = new int[N];
for (int pos = 0, index = 0; ;)
{
for (; pos < N; pos++, index++)
{
indices[pos] = index;
result[pos] = input[index];
}
yield return result;
do
{
if (pos == 0) yield break;
index = indices[--pos] + 1;
}
while (index > input.Length - N + pos);
}
}
}
As in the other implementations, the method yields one and the same internal buffer, which is useful when you need just to iterate and process the resulting set once. If you need to store the combinations, then you need to clone the returned array before storing it. Here is a sample usage like in your scenario:
var input = Enumerable.Range(1, 20);
var result = input
.Distinct()
.ToArray()
.GetCombinations(5)
.Select(c => (int[])c.Clone())
.ToList();
UPDATE: The GetCombinations method basically emulates N nested loops like this (in pseudo code):
for (int i0 = 0; i0 <= input.Length - N; i0++)
for (int i1 = i0 + 1; i1 <= input.Length - N + 1; i1++)
for (int i2 = i1 + 1; i2 <= input.Length - N + 2; i2++)
...
for (int iN-1 = iN-2 + 1; iN-1 <= input.Length - 1; iN-1++)
yield { input[i0], input[i1], input[i2], ..., input[iN-1] }
In case of a tractable set of 9 elements (or max 25-30) and subset of 5, the code could be based on a recursive function
static void Main(string[] args)
{
foreach (var item in ListPerm())
{
Console.WriteLine(String.Join(",", item));
}
Console.Read();
}
private static List<List<int>> ListPerm(HashSet<int> mySet = null, int deep = 5)
{
if (mySet == null)
{
mySet = initSet(8);
}
if (deep <= 0)
{
return Enumerable.Empty<List<int>>().ToList();
}
List<List<int>> all = new List<List<int>>();
for (int i = 0; i < mySet.Count - deep + 1; i++)
{
if (deep == 1)
{
var list = new List<int>() { mySet.ElementAt(i) };
all.Add(list);
}
foreach (var item in ListPerm(new HashSet<int>(mySet.Skip(i+1)), deep - 1))
{
var list = new List<int>() { mySet.ElementAt(i) };
list.AddRange(item);
all.Add(list);
}
}
return all;
}
private static HashSet<int> initSet(int lenght)
{
HashSet<int> ret = new HashSet<int>();
for (int i = 0; i < lenght; i++)
{
ret.Add(i * 1 + 1); // just an example...
};
return ret;
}
Reengineering
Now, let me optimize the above code into a more performant function, that takes 3.2 seconds to get the combinations of 8 integers out of 30 on my standard laptop.
private static int[][] ListPerm(int[] mySet, int deep)
{
var all = new List<int[]>();
if (deep == 1)
{
return mySet.Select(x => new int[] { x }).ToArray();
}
else
{
var mySubSet = new int[mySet.Length - 1];
Array.Copy(mySet, 1, mySubSet, 0, mySubSet.Length);
var perm1st = ListPerm(mySubSet, deep - 1);
for (int i = 0; i < mySet.Length - deep + 1; i++)
{
var permn = perm1st.Select(x =>
{
var z = new int[x.Length + 1];
z[0] = mySet[i];
x.CopyTo(z, 1);
return z;
}
);
all.AddRange(permn);
int start = Array.FindIndex(perm1st, item => item[0] != mySet[i + 1]);
if (start > 0)
{
var temp_cpy = new int[perm1st.Length - start][];
Array.Copy(perm1st, start, temp_cpy, 0, temp_cpy.Length);
perm1st = temp_cpy;
}
}
}
return all.ToArray();
}
Benchmark
Here it is a comparison of Ivan's, my and the community wiki algorithms for the combinations of 5 ints in 20.
Results
wiki perm: 00:00:00.0950055
writing wiki perm: 00:00:00.0460026
Ivan perm: 00:00:00.0400023
writing Ivan perm: 00:00:00.0260015
my perm: 00:00:00.0110006
writing my perm: 00:00:00.0300017
Test Code
var input = Enumerable.Range(1, 20);
int deep = 5;
var start = DateTime.Now;
var wiki = Algorithms.Combinations(input, deep).ToArray();
Console.WriteLine("wiki perm: {0}", DateTime.Now - start);
start = DateTime.Now;
StreamWriter sw0 = new StreamWriter(#"C:\dev\SO\Algo\perm0.txt", false);
foreach (var item in wiki)
{
sw0.WriteLine(String.Join(",", item));
}
sw0.Close();
Console.WriteLine("writing wiki perm: {0}", DateTime.Now - start);
start = DateTime.Now;
start = DateTime.Now;
var result = input
.Distinct()
.ToArray()
.GetCombinations(deep)
.Select(c => (int[])c.Clone())
.ToList();
Console.WriteLine("Ivan perm: {0}", DateTime.Now - start);
start = DateTime.Now;
StreamWriter sw1 = new StreamWriter(#"C:\dev\SO\Algo\perm1.txt", false);
foreach (var item in result)
{
sw1.WriteLine(String.Join(",", item));
}
sw1.Close();
Console.WriteLine("writing Ivan perm: {0}", DateTime.Now - start);
start = DateTime.Now;
var myPerm = ListPermSO(input.ToArray(), deep);
Console.WriteLine("my perm: {0}", DateTime.Now - start);
start = DateTime.Now;
StreamWriter sw2 = new StreamWriter(#"C:\dev\SO\Algo\perm2.txt", false);
foreach (var item in myPerm)
{
sw2.WriteLine(String.Join(",", item));
}
sw2.Close();
Console.WriteLine("writing my perm: {0}", DateTime.Now - start);
Console.Read();