Permutations using same letters - c#

I am current working on a project where I need to generate all possible permutations from a given set of characters. I am currently using this code:
public static IEnumerable<string> AllPermutations(this IEnumerable<char> s)
{
return s.SelectMany(x =>
{
var index = Array.IndexOf(s.ToArray(), x);
return s.Where((y, i) => i != index).AllPermutations().Select(y => new string(new[] { x }.Concat(y).ToArray())).Union(new[] { new string(new[] { x }) });
}).Distinct();
}
From this answer.
The problem I have is that it won't generate permuations that use the same letter more than once.
For example if I used abcde as the input I need it to generate combinations like aaaaa and dcc etc.
I'm not experienced enough with LINQ to understand where the code is stopping duplicate letters. Any help is greatly appreciated.

This might work, but I'm sure it could be done more efficiently (taking the counting prompt from PeskyGnat):
static IEnumerable<string> GetVariations(string s)
{
int[] indexes = new int[s.Length];
StringBuilder sb = new StringBuilder();
while (IncrementIndexes(indexes, s.Length))
{
sb.Clear();
for (int i = 0; i < indexes.Length; i++)
{
if (indexes[i] != 0)
{
sb.Append(s[indexes[i]-1]);
}
}
yield return sb.ToString();
}
}
static bool IncrementIndexes(int[] indexes, int limit)
{
for (int i = 0; i < indexes.Length; i++)
{
indexes[i]++;
if (indexes[i] > limit)
{
indexes[i] = 1;
}
else
{
return true;
}
}
return false;
}
Edit: Changed to use yield return as per Rawlings suggestion. Much better memory usage if you don't need to keep all the results and you can start using the results before they've all been generated.

I'm amazed this works. It basically goes "make a list of strings from the characters. Then to each string taken from the list, add each character again, and add the resulting strings to the list. Repeat until you've got the right length."
public static IEnumerable<string> BuildStrings(this IEnumerable<char> alphabet)
{
var strings = alphabet.Select(c => c.ToString());
for (int i = 1; i < alphabet.Count(); i++)
{
strings = strings.Union(strings.SelectMany(s => alphabet.Select(c => s + c.ToString())));
}
return strings;
}

A funny one using only recursive lambdas via a fixpoint operator (thx #Rawling for the SelectMany)
// Fix point operator
public static Func<T, TResult> Fix<T, TResult>(Func<Func<T, TResult>, Func<T, TResult>> f)
{
return t => f(Fix<T, TResult>(f))(t);
}
And then
var chars = new[] {'a','b','c','d','e'}.Select(c=>c.ToString()) ;
var result = Fix<int,IEnumerable<string>>(
f =>
x =>
x == 1
? chars
: chars.Union(f(x - 1).SelectMany(s => chars.Select(c => s + c))))(chars.Count());

Related

How to sort large numbers stored in a string array?

I need to sort the large numbers stored as string in string array but my algorithm and .net built Array sort method doesn't work.
I tried to convert the number into long or ulong but that throw exception of overflow.
Here is the code that I tried:
string[] unsorted = { "1","2","100","12303479849857341718340192371",
"3084193741082937","3084193741082938","111","200" };
for (int index = 0; index < unsorted.Length - 1; index++)
{
for (int count = 0; count < unsorted.Length - index - 1; count++)
{
if (string.Compare(unsorted[count], unsorted[count + 1]) == 1)
{
string temp = unsorted[count];
unsorted[count] = unsorted[count + 1];
unsorted[count + 1] = temp;
}
}
}
Also used the following method:
Array.Sort(unsorted);
The array should be sorted correctly.
You could use BigInteger.Parse and use Linq's OrderBy on it. For example:
var sorted = unsorted.Select(BigInteger.Parse).OrderBy(e => e).ToArray();
If you need it back as string:
var sorted = unsorted.Select(BigInteger.Parse).OrderBy(e => e).Select(e => e.ToString()).ToArray();
This has a drawback in converting it first to a BigInteger, but probably you need it anyway. However compared to IO and Database access, this nothing adds to a typical application performance.
Pro: Readable
Contra: Probably not the most efficient solution.
Try following :
string[] unsorted = { "1","2","100","12303479849857341718340192371",
"3084193741082937","3084193741082938","111","200" };
var groups = unsorted.OrderBy(x => x.Length).GroupBy(x => x.Length).ToArray();
List<string> results = new List<string>();
foreach (var group in groups)
{
string[] numbers = group.ToArray();
for(int i = 0; i < numbers.Count() - 1; i++)
{
for(int j = i + 1; j < numbers.Count(); j++)
{
if(numbers[i].CompareTo(numbers[j]) == 1)
{
string temp = numbers[i];
numbers[i] = numbers[j];
numbers[j] = temp;
}
}
}
results.AddRange(numbers);
}
You don't have an array of numbers, you have an array of strings. So they're being sorted alpha-numerically.
One option would be to use the BigInteger class to store them as numbers:
BigInteger[] unsorted = {
BigInteger.Parse("1"),
BigInteger.Parse("2"),
BigInteger.Parse("100"),
BigInteger.Parse("12303479849857341718340192371"),
BigInteger.Parse("3084193741082937"),
BigInteger.Parse("3084193741082938"),
BigInteger.Parse("111"),
BigInteger.Parse("200")
};
Failing that, if you want to keep them as strings then you can left-pad them with zeros to make the lengths consistent so the alphanumeric sorting would work:
string[] unsorted = {
"00000000000000000000000000001",
"00000000000000000000000000002",
"00000000000000000000000000100",
"12303479849857341718340192371",
"00000000000003084193741082937",
"00000000000003084193741082938",
"00000000000000000000000000111",
"00000000000000000000000000200"
};
If you choose the former, just change the types in your if block to also be BigInteger as well.
If we want to sort very big numbers stored as strings, without changing string to BigInteger, it's better sort them according to it's length at first and then according to lexicographic order. We can see the sample code below:
using System;
using System.Linq;
public class Test
{
public static void Main()
{
string[] unsorted = { "1","2", "100","12303479849857341718340192371",
"3084193741082937","3084193741082938","111","200" };
unsorted.OrderBy(s => s.Length).ThenBy(s => s);
Console.WriteLine("Sorted numbers are:");
foreach (var x in unsorted) {
Console.WriteLine(x);
}
}
}
Note: In order to use OrderBy and ThenBy functionality , we have to include using System.Linq to our program.
For an elegant solution you can use linq, you will have a minimum of code with good performance.
var result = unsorted.Select(e => decimal.Parse(e)).OrderBy(e => e);
The system must be like following. You can transfer values in the array to an arraylist then you can parse them all to BigInteger by for loop. And finally you can sort the list :
BigInteger[] unsorted;
var bigIntegers = new List<System.Numerics.BigInteger>();
for (int index = 0; index < unsorted.Length - 1; index++)
{
bigIntegers[i] = BigInteger.Parse[i]
}
bigIntegers.sort();
Another variation:
static void Main(string[] args)
{
List<string> unsorted = new List<string>(new string[] {"1","2","100","12303479849857341718340192371",
"3084193741082938","3084193741082937", "111","200" });
unsorted.Sort((x, y) => (x.Length != y.Length ? x.Length.CompareTo(y.Length) : x.CompareTo(y)));
foreach(string number in unsorted)
{
Console.WriteLine(number);
}
Console.Write("Press Enter to quit");
Console.ReadLine();
}
Building upon #jdweng's answer, but further reducing it by eliminating the 'manual' bubble sort:
string[] result =
unsorted.OrderBy(x => x.Length)
.GroupBy(x => x.Length)
.SelectMany(x => x.OrderBy(y => y))
.ToArray();
Or some other variation of the same theme:
using System.Collections.Generic;
using System.Linq;
...
string[] result =
unsorted.OrderBy(x => x, Comparer<string>.Create((a, b) => a.Length == b.Length ? a.CompareTo(b) : a.Length - b.Length))
.GroupBy(x => x.Length)
.SelectMany(x => x)
.ToArray();
(As noted by #fester's comment underneath #jdweng's answer, this approach will not work reliably if some of the strings are numbers with prepended zeros, such as "00123" for example.)
package com.solution.sorting;
import java.util.Arrays;
import java.util.Comparator;
public class ArraySort {
public static void main(String[] args) {
String[] number = { "3", "2", "4", "10", "11", "6", "5", "8", "9", "7" };
String[] unsorted = { "8", "1", "2", "100", "12303479849857341718340192371", "3084193741082937",
"3084193741082938", "111", "200" };
Arrays.sort(number);
for (String s : number)
System.out.println("number="+s);
//
Arrays.sort(unsorted, new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
return compareStrings(o1,o2);//Integer.valueOf(o1).compareTo(Integer.valueOf(o2));
}
});
for (String s : unsorted)
System.out.println("number1=" + s);
}
private static int compareStrings(String s1, String s2) {
//
if (s1.length() < s2.length()) {
return -1;
} else if (s1.length() > s2.length()) {
return 1;
}
for (int i = 0; i < s1.length(); i++) {
if ((int) s1.charAt(i) < (int) s2.charAt(i))
return -1;
if ((int) s1.charAt(i) > (int) s2.charAt(i))
return 1;
}
return 0;
}
}
For extremely large numbers where Primitive Data Types might fail, create a Comparator that first sorts the String by length and then sorts the String by the value of the same length.
Arrays.sort(array, new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
/** Sort by Length */
if (o1.length() < o2.length()) {
return -1;
}
if (o1.length() > o2.length()) {
return 1;
}
/** Sort by the value of the same Length */
return o1.compareTo(o2);
}
});

Refactor an ugly loop into LINQ

I have the following peace of code, that factors an int to prime numbers:
private static IEnumerable<int> Factor(int input)
{
IList<int> result = new List<int>();
while (true)
{
var theSmallestDivisor = GetTheSmallestDivisor(input);
if (theSmallestDivisor == 0)
{
result.Add(input);
return result;
}
result.Add(theSmallestDivisor);
input = input/theSmallestDivisor;
}
}
I'm looking for hints on how to improve it, possibly using LINQ.
Here's an iterator version:
private static IEnumerable<int> Factor(int input)
{
while (true)
{
var theSmallestDivisor = GetTheSmallestDivisor(input);
if (theSmallestDivisor == 0)
{
yield return input;
yield break;
}
yield return theSmallestDivisor;
input = input / theSmallestDivisor;
}
}
LINQ would only make this code less readable in that particular case.
LINQ's operators are mostly designed to generating a new list from an existing list. e.g.
IEnumerable<B> LinqOperator(this IEnumerable<A> list, ...)
Not so much for generating a list from scratch as you a trying to do.
But, since you are returning IEnumerable, you may as well make it lazy:
private static IEnumerable<int> Factor(int input)
{
while (true)
{
var theSmallestDivisor = GetTheSmallestDivisor(input);
if (theSmallestDivisor == 0)
{
yield return input;
yield break;
}
yield return theSmallestDivisor;
input = input/theSmallestDivisor;
}
}
public IEnumerable<int> GetFactors(int input)
{
int first = Primes()
.TakeWhile(x => x <= Math.Sqrt(input))
.FirstOrDefault(x => input % x == 0);
return first == 0
? new[] { input }
: new[] { first }.Concat(GetFactors(input / first));
}

Remove from String Array what is in List

I have a String Array x and a List y and I want to remove all data from Y from the List X, how to do that in the fastest way?
e.g.:
X:
1) "aaa.bbb.ccc"
2) "ddd.eee.fff"
3) "ggg.hhh.jjj"
Y:
1) "bbb"
2) "fff"
Result should be a new List in Which only 3) exist because X.1 gets deleted by Y.1 and X.2 gets deleted by Y.2
How to do that?
I know I could do a foreach on the List X and check with everything in List Y, bit is that the fastest way?
The most convenient would be
var Z = X.Where(x => !x.Split('.').Intersect(Y).Any()).ToList();
That is not the same as "fastest". Probably the fastest (runtime) way to do that is to use a token search, like:
public static bool ContainsToken(string value, string token, char delimiter = '.')
{
if (string.IsNullOrEmpty(token)) return false;
if (string.IsNullOrEmpty(value)) return false;
int lastIndex = -1, idx, endIndex = value.Length - token.Length, tokenLength = token.Length;
while ((idx = value.IndexOf(token, lastIndex + 1)) > lastIndex)
{
lastIndex = idx;
if ((idx == 0 || (value[idx - 1] == delimiter))
&& (idx == endIndex || (value[idx + tokenLength] == delimiter)))
{
return true;
}
}
return false;
}
then something like:
var list = new List<string>(X.Length);
foreach(var x in X)
{
bool found = false;
foreach(var y in Y)
{
if(ContainsToken(x, y, '.'))
{
found = true;
break;
}
}
if (!found) list.Add(x);
}
This:
doesn't allocate arrays (for the output of Split, of for the params char[] of Split)
doesn't create any new string instances (for the output of Split)
doesn't use delegate abstraction
doesn't have captured scopes
uses the struct custom iterator of List<T> rather than the class iterator of IEnumerable<T>
starts the new List<T> with the appropriate worst-case size to avoid reallocations
Iterating over X and Y would indeed be the fastest option because you have this Contains constraint. I really don't see any other way.
It should not be a foreach over X though, because you cannot modify the collection you iterate over with foreach.
So an option would be:
for (int counterX = 0; counterX < X.Length; counterX++)
{
for(int counterY = 0; counterY < Y.Length; counterY++)
{
if (X[counterX].Contains(Y[counterY]))
{
X.RemoveAt(counterX--);
counterY = Y.Length;
}
}
}
This should do it (mind you, this code is not tested).
I think that a fairly fast approach would be to use List's built-in RemoveAll() method:
List<string> x = new List<string>
{
"aaa.bbb.ccc",
"ddd.eee.fff",
"ggg.hhh.jjj"
};
List<string> y = new List<string>
{
"bbb",
"fff"
};
x.RemoveAll(s => y.Any(s.Contains));
(Note that I am assuming that you have two lists, x and y. Your OP mentions a string array but then goes on to talk about "List X" and "List Y", so I'm ignoring the string array bit.)
Try this, using Aggregate function
var xArr = new string[] { "aaa.bbb.ccc", "ddd.eee.fff", "ggg.hhh.jjj" };
var yList = new List<string> { "bbb", "fff" };
var result = xArr.Aggregate(new List<string> { }, (acc, next) =>
{
var elems = next.Split('.');
foreach (var y in yList)
if (elems.Contains(y))
return acc;
acc.Add(next);
return acc;
});
If you've got a relatively small list the performance ramifications wouldn't really be a big deal. This is the simplest foreach solution I could come up with.
List<string> ListZ = ListX.ToList();
foreach (string x in ListX)
{
foreach (string y in ListY)
{
if (x.Contains(y))
ListZ.Remove(x);
}
}

How to select 2 items at a time?

I was writing a PascalCaseParser using Regex.Split and I came to the desire to select two items from an collection at a time.
This example code demonstrates.
void Main()
{
string pascalCasedString = "JustLikeYouAndMe";
var words = WordsFromPascalCasedString(pascalCasedString);
words.Dump();
}
IEnumerable<string> WordsFromPascalCasedString(string pascalCasedString)
{
var rx = new Regex("([A-Z])");
return rx.Split(pascalCasedString)
.Where(c => !string.IsNullOrEmpty(c))
// how to select 2 elements at a time?
;
}
The result of above code is:
IEnumerable<String> (10 items)
J
ust
L
ike
Y
ou
A
nd
M
e
Every two elements of the collection make one result that I want the function WordsFromPascalCasedString to yield.
My questions is: How would you, in general, deal with a requirement to return two items at a time. I'm curious if there are any interesting non-brute-force approaches.
Personally, I'd go with Simon Belanger's answer in this particular case. But in general, to select consecutive pairs, from an IEnumerable, you'd use this:
IEnumerable<Tuple<string, string>> WordsFromPascalCasedString(string pascalCasedString)
{
var rx = new Regex("([A-Z])");
var array = rx.Split(pascalCasedString)
.Where(c => !string.IsNullOrEmpty(c))
.ToArray();
var items = Enumerable.Range(0, array.Length / 2)
.Select(i => Tuple.Create(array[i * 2], array[i * 2 + 1]);
}
Or this, which takes more effort, but it's reusable and more efficient:
IEnumerable<Tuple<T, T>> Pairs<T>(IEnumerable<T> input)
{
var array = new T[2];
int i = 0;
foreach(var x in input)
{
array[i] = x;
i = (i + 1) % 2;
if (i == 0)
{
yield return Tuple.Create(array[0], array[1]);
}
}
}
IEnumerable<Tuple<string, string>> WordsFromPascalCasedString(string pascalCasedString)
{
var rx = new Regex("([A-Z])");
var output = rx.Split(pascalCasedString)
.Where(c => !string.IsNullOrEmpty(c));
var items = Pairs(output);
}
It can easily be extended to groups of n:
IEnumerable<IEnumerable<T>> Batches<T>(IEnumerable<T> input, int n)
{
var array = new T[n];
int i = 0;
foreach(var x in input)
{
array[i] = x;
i = (i + 1) % n;
if (i == 0)
{
yield return array.ToArray();
}
}
if (i != 0)
{
yield return array.Take(i);
}
}
A similar method exists in MoreLINQ.
The regex should be ([A-Z][a-z]*). Adjust the last portion if you want to include numbers too. Use + instead of * if you want at least one lowercase element after the uppercase delimiter.
Edit As for the actual question, you will need to materialize and iterate in a for loop for better performance (passing the list once). In your specific problem, you can just use Regex.Matches
var result = Regex.Matches("([A-Z][a-z]*)([A-Z][a-z]*)?", "AbCdEfGhIj")
.OfType<Match>()
.Where(m => m.Success)
.Select(m => Tuple.Create(m.Groups[1].Value, m.Groups[2].Value));
This is just to share, I'm throwing the solution I came up with after getting inspired by the other answers. It is not better than the others...
void Main()
{
string pascalCasedString = "JustLikeYouAndMe";
var words = WordsFromPascalCasedString(pascalCasedString);
words.Dump();
}
IEnumerable<string> WordsFromPascalCasedString(string pascalCasedString)
{
var rx = new Regex("([A-Z])");
return rx.Split(pascalCasedString)
.Where(c => !string.IsNullOrEmpty(c))
.InPieces(2)
.Select(c => c.ElementAt(0) + c.ElementAt(1));
}
static class Ext
{
public static IEnumerable<IEnumerable<T>> InPieces<T>(this IEnumerable<T> seq, int len)
{
if(!seq.Any())
yield break;
yield return seq.Take(len);
foreach (var element in InPieces(seq.Skip(len), len))
yield return element;
}
}
Easiest is to write function that simply returns pairs.
Something like:
IEnumerable<Tuple<T,T>> Pairs<T>(IEnumerable<T> items)
{
T first = default(T);
bool hasFirst = false;
foreach(T item in items)
{
if (hasFirst)
yield return Tuple.Create(first, item);
else
first = item;
hasFirst = !hasFirst;
}
}
Aggregate is likely only one one-line approach. This is purely entertainment code due to amount of garbage created on a way, but there is no mutable objects used.
IEnumerable<Tuple<T,T>> Pairs<T>(IEnumerable<T> collection)
{
return collection
.Aggregate(
Tuple.Create(false, default(T), Enumerable.Empty<Tuple<T,T>>()),
(accumulate, item)=> !accumulate.Item1 ?
Tuple.Create(true, item, accumulate.Item3) :
Tuple.Create(false, default(T),
accumulate.Item3.Concat(
Enumerable.Repeat(Tuple.Create(accumulate.Item2, item), 1))),
accumulate => accumulate.Item3);
}
Zip of odd and even elements (index %2 ==/!= 0) is 2 line approach. Note that iterates source collection twice.
IEnumerable<Tuple<T,T>> Pairs<T>(IEnumerable<T> collection)
{
return collection
.Where((item, index)=>index %2 == 0)
.Zip(collection.Where((item, index)=>index %2 != 0),
(first,second)=> Tuple.Create(first,second));
}

Split and join multiple logical "branches" of string data

I know there's a couple similarly worded questions on SO about permutation listing, but they don't seem to be quite addressing really what I'm looking for. I know there's a way to do this but I'm drawing a blank. I have a flat file that resembles this format:
Col1|Col2|Col3|Col4|Col5|Col6
a|b,c,d|e|f|g,h|i
. . .
Now here's the trick: I want to create a list of all possible permutations of these rows, where a comma-separated list in the row represents possible values. For example, I should be able to take an IEnumerable<string> representing the above to rows as such:
IEnumerable<string> row = new string[] { "a", "b,c,d", "e", "f", "g,h", "i" };
IEnumerable<string> permutations = GetPermutations(row, delimiter: "/");
This should generate the following collection of string data:
a/b/e/f/g/i
a/b/e/f/h/i
a/c/e/f/g/i
a/c/e/f/h/i
a/d/e/f/g/i
a/d/e/f/h/i
This to me seems like it would elegantly fit into a recursive method, but apparently I have a bad case of the Mondays and I can't quite wrap my brain around how to approach it. Some help would be greatly appreciated. What should GetPermutations(IEnumerable<string>, string) look like?
You had me at "recursive". Here's another suggestion:
private IEnumerable<string> GetPermutations(string[] row, string delimiter,
int colIndex = 0, string[] currentPerm = null)
{
//First-time initialization:
if (currentPerm == null) { currentPerm = new string[row.Length]; }
var values = row[colIndex].Split(',');
foreach (var val in values)
{
//Update the current permutation with this column's next possible value..
currentPerm[colIndex] = val;
//..and find values for the remaining columns..
if (colIndex < (row.Length - 1))
{
foreach (var perm in GetPermutations(row, delimiter, colIndex + 1, currentPerm))
{
yield return perm;
}
}
//..unless we've reached the last column, in which case we create a complete string:
else
{
yield return string.Join(delimiter, currentPerm);
}
}
}
I'm not sure whether this is the most elegant approach, but it might get you started.
private static IEnumerable<string> GetPermutations(IEnumerable<string> row,
string delimiter = "|")
{
var separator = new[] { ',' };
var permutations = new List<string>();
foreach (var cell in row)
{
var parts = cell.Split(separator);
var perms = permutations.ToArray();
permutations.Clear();
foreach (var part in parts)
{
if (perms.Length == 0)
{
permutations.Add(part);
continue;
}
foreach (var perm in perms)
{
permutations.Add(string.Concat(perm, delimiter, part));
}
}
}
return permutations;
}
Of course, if the order of the permutations is important, you can add an .OrderBy() at the end.
Edit: added an alernative
You could also build a list of string arrays, by calculating some numbers before determining the permutations.
private static IEnumerable<string> GetPermutations(IEnumerable<string> row,
string delimiter = "|")
{
var permutationGroups = row.Select(o => o.Split(new[] { ',' })).ToArray();
var numberOfGroups = permutationGroups.Length;
var numberOfPermutations =
permutationGroups.Aggregate(1, (current, pg) => current * pg.Length);
var permutations = new List<string[]>(numberOfPermutations);
for (var n = 0; n < numberOfPermutations; n++)
{
permutations.Add(new string[numberOfGroups]);
}
for (var position = 0; position < numberOfGroups; position++)
{
var permutationGroup = permutationGroups[position];
var numberOfCharacters = permutationGroup.Length;
var numberOfIterations = numberOfPermutations / numberOfCharacters;
for (var c = 0; c < numberOfCharacters; c++)
{
var character = permutationGroup[c];
for (var i = 0; i < numberOfIterations; i++)
{
var index = c + (i * numberOfCharacters);
permutations[index][position] = character;
}
}
}
return permutations.Select(p => string.Join(delimiter, p));
}
One algorithm you can use is basically like counting:
Start with the 0th item in each list (00000)
Increment the last value (00001, 00002 etc.)
When you can't increas one value, reset it and increment the next (00009, 00010, 00011 etc.)
When you can't increase any value, you're done.
Function:
static IEnumerable<string> Permutations(
string input,
char separator1, char separator2,
string delimiter)
{
var enumerators = input.Split(separator1)
.Select(s => s.Split(separator2).GetEnumerator()).ToArray();
if (!enumerators.All(e => e.MoveNext())) yield break;
while (true)
{
yield return String.Join(delimiter, enumerators.Select(e => e.Current));
if (enumerators.Reverse().All(e => {
bool finished = !e.MoveNext();
if (finished)
{
e.Reset();
e.MoveNext();
}
return finished;
}))
yield break;
}
}
Usage:
foreach (var perm in Permutations("a|b,c,d|e|f|g,h|i", '|', ',', "/"))
{
Console.WriteLine(perm);
}
I really thought this would be a great recursive function, but I ended up not writing it that way. Ultimately, this is the code I created:
public IEnumerable<string> GetPermutations(IEnumerable<string> possibleCombos, string delimiter)
{
var permutations = new Dictionary<int, List<string>>();
var comboArray = possibleCombos.ToArray();
var splitCharArr = new char[] { ',' };
permutations[0] = new List<string>();
permutations[0].AddRange(
possibleCombos
.First()
.Split(splitCharArr)
.Where(x => !string.IsNullOrEmpty(x.Trim()))
.Select(x => x.Trim()));
for (int i = 1; i < comboArray.Length; i++)
{
permutations[i] = new List<string>();
foreach (var permutation in permutations[i - 1])
{
permutations[i].AddRange(
comboArray[i].Split(splitCharArr)
.Where(x => !string.IsNullOrEmpty(x.Trim()))
.Select(x => string.Format("{0}{1}{2}", permutation, delimiter, x.Trim()))
);
}
}
return permutations[permutations.Keys.Max()];
}
... my test conditions provided me with exactly the output I expected:
IEnumerable<string> row = new string[] { "a", "b,c,d", "e", "f", "g,h", "i" };
IEnumerable<string> permutations = GetPermutations(row, delimiter: "/");
foreach(var permutation in permutations)
{
Debug.Print(permutation);
}
This produced the following output:
a/b/e/f/g/i
a/b/e/f/h/i
a/c/e/f/g/i
a/c/e/f/h/i
a/d/e/f/g/i
a/d/e/f/h/i
Thanks to everyone's suggestions, they really were helpful in sorting out what needed to be done in my mind. I've upvoted all your answers.

Categories

Resources