Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Words combinations without repetition

I have 10 words. How can I get all possible combinations of 5 words (n=10, k=5). The order does not matter.

For example: "A", "B", "C", if k=2 (n=3 in this case), it would like AB, BC and AC. Maybe you know some usefull code or example.

P.S. Sorry if I'm not right enough cause I don't know English very good.

like image 795
Frankie Drake Avatar asked Feb 27 '11 10:02

Frankie Drake


People also ask

How do you find the combination without repetition?

Combinations are selections of objects, with or without repetition, order does not matter. The number of k-element combinations of n objects, without repetition is Cn,k = (n k ) = n! k!( n − k)! .

How many combinations of 4 items have no repeats?

Answer and Explanation: The number of possible combinations with 4 numbers without repetition is 15. The formula we use to calculate the number of n element combinations when repetition is not allowed is 2n - 1.

How many combinations of 5 items are there without repeating?

Note that your choice of 5 objects can take any order whatsoever, because your choice each time can be any of the remaining objects. So we say that there are 5 factorial = 5! = 5x4x3x2x1 = 120 ways to arrange five objects.

How many combinations are there with 10 numbers without repetition?

Answer and Explanation: If repetition is allowed, then the number of permutations of 10 digits is 10,000,000,000. If repetition is not allowed, then the number of permutations of 10 digits is 3,628,800.


2 Answers

What you are trying to do is get all the permutations of a collection.

  • Unique permutations of list
  • permutations of k objects from a set of n algorithm

Here is the code snippet:

static void Main(string[] args)
{
    var list = new List<string> { "a", "b", "c", "d", "e" };
    var result = GetPermutations(list, 3);
    foreach (var perm in result)
    {
        foreach (var c in perm)
        {
            Console.Write(c + " ");
        }
        Console.WriteLine();
    }
    Console.ReadKey();
}

static IEnumerable<IEnumerable<T>> GetPermutations<T>(IEnumerable<T> items, int count)
{
    int i = 0;
    foreach (var item in items)
    {
        if (count == 1)
            yield return new T[] { item };
        else
        {
            foreach (var result in GetPermutations(items.Skip(i + 1), count - 1))
                yield return new T[] { item }.Concat(result);
        }

        ++i;
    }
}

Outputs:

a b c 
a b d 
a b e 
a c d 
a c e 
a d e 
b c d 
b c e 
b d e 
c d e 
like image 194
jrbeverly Avatar answered Oct 06 '22 00:10

jrbeverly


Here's what I put together:

static class LinqExtensions
{
    public static IEnumerable<IEnumerable<T>> CombinationsWithoutRepetition<T>(
        this IEnumerable<T> items,
        int ofLength)
    {
        return (ofLength == 1) ?
            items.Select(item => new[] { item }) :
            items.SelectMany((item, i) => items.Skip(i + 1)
                                               .CombinationsWithoutRepetition(ofLength - 1)
                                               .Select(result => new T[] { item }.Concat(result)));
    }

    public static IEnumerable<IEnumerable<T>> CombinationsWithoutRepetition<T>(
        this IEnumerable<T> items,
        int ofLength,
        int upToLength)
    {
        return Enumerable.Range(ofLength, Math.Max(0, upToLength - ofLength + 1))
                         .SelectMany(len => items.CombinationsWithoutRepetition(ofLength: len));
    }

}

...

foreach (var c in new[] {"a","b","c","d"}.CombinationsWithoutRepetition(ofLength: 2, upToLength: 4))
{
    Console.WriteLine(string.Join(',', c));
}

produces:

a,b
a,c
a,d
b,c
b,d
c,d
a,b,c
a,b,d
a,c,d
b,c,d
a,b,c,d

Note that this is concise but inefficient and should not be used for large sets or inner loops. Notably, the short arrays are re-created multiple times and could be memoized, and the IEnumerable will be iterated multiple times, which can cause unexpected work if care is not taken.

Also, if the input contains duplicates then the output will as well. Either use .Distinct().ToArray() first, or use another solution which includes equality checking and, presumably, takes an IEqualityComparer for generality.

like image 36
Tim Sylvester Avatar answered Oct 05 '22 23:10

Tim Sylvester