1

I have a list and I need to output each subset of the list

for example a b c d e

would output to

 a
 b
 c  
 d 
 e 
 ab  
 ac  
 ad 
 ae

 abc
 abd 
 abe
 bcd
 bce
 ....
 abcde

I believe the correct term is combination no element should be duplicated on the same line

I was going to attempt this with a series of loops but im not even sure wehre to start

any suggestions?

Crash893
  • 11,428
  • 21
  • 88
  • 123
  • 2
    duplicated of ?? http://stackoverflow.com/questions/756055/listing-all-permutations-of-a-string-integer – vaquito Feb 16 '11 at 22:45
  • 9
    `aaaaa` is not a **subset** of `a b c d e`. What is the actual definition of the result you're looking for? Apparently, elements from your original list can be repeated, but how many times? – vlad Feb 16 '11 at 22:46
  • It appears that he wants all sets of sizes 1 to N that can be formed using any number of items from the original set. – Ron Warholic Feb 16 '11 at 22:48
  • 1
    Agreed with @vlad, if your 2-letter sequences had gone `ae` `ba` `bb` `bc` `...` `ee` it would have been a little more clear that you're going for all sequences of these chars, but you sorta skipped that. – Daniel DiPaolo Feb 16 '11 at 22:49
  • 1
    Agree with Ron, would probably phrase it as words of maximum length 5 that can be formed from the alphabet { a, b, c, d, e } – LorenVS Feb 16 '11 at 22:53
  • @vlad sorry you are correct aaaa is not a subset I did it by hand – Crash893 Feb 16 '11 at 23:04
  • I updated the question to reflect – Crash893 Feb 16 '11 at 23:06
  • @vaquito no its not that appears to be a permutation answer I would never need any one element more than once – Crash893 Feb 16 '11 at 23:07
  • I have an answer that solves your original question... I deleted it to avoid downvotes after you changed your answer. You definitely want subsets,right? – Sapph Feb 16 '11 at 23:07
  • @Sapph yes ( I never down vote unless its completely off topic) i updated the question again to clarify more – Crash893 Feb 16 '11 at 23:10
  • Why the hate with the down vote? its a valid question! – Crash893 Feb 16 '11 at 23:13
  • @Crash893 it looks to me like it's still slightly misleading. if all you want are subsets, then no elements should appear in the results twice (unless they appear in the original list twice), so `aab` and `acc` should not be part of the results list. Also, if this is the case, you are looking for permutations of a collection of elements, and @vaquito is correct that this is a duplicate question. – vlad Feb 16 '11 at 23:14
  • I updated the question 11min ago – Crash893 Feb 16 '11 at 23:18
  • No i don't need permutations Just combinations – Crash893 Feb 16 '11 at 23:19
  • I'm heading home ill check back in an hour or so – Crash893 Feb 16 '11 at 23:21
  • Possible duplicate of [How to get all subsets of an array?](https://stackoverflow.com/questions/999050/how-to-get-all-subsets-of-an-array) – dharmatech Sep 08 '17 at 04:02
  • Wow! you went wayyyyyyyyyy back to find that match – Crash893 Sep 15 '17 at 19:17

5 Answers5

6

This will generate the set you want, but in a different order (I sort by alphabet at the end, you'd want to sort by length as well).

You'll end up with:

a ab abc abcd abcde abce ... d de e

So, every possible subset (aside from the empty string), while maintaining the order of the original list.

The idea is to add each element to to a growing list. With every new element, add it first, and then add it to all existing elements.

So, start with 'a'.

Go on to 'b'. Add it to the list. We now have {'a', 'b'}.

Add it to existing elements, so we have 'ab'. Now we have {'a', 'b', 'ab'}.

Then 'c', and add it to existing elements to get 'ac', 'bc', 'abc': {'a', 'b', 'ab', 'c', 'ac', 'bc', abc'}. So forth until we're done.

        string set = "abcde";

        // Init list
        List<string> subsets = new List<string>();

        // Loop over individual elements
        for (int i = 1; i < set.Length; i++)
        {
            subsets.Add(set[i - 1].ToString());

            List<string> newSubsets = new List<string>();

            // Loop over existing subsets
            for (int j = 0; j < subsets.Count; j++)
            {
                string newSubset = subsets[j] + set[i];
                newSubsets.Add(newSubset);
            }

            subsets.AddRange(newSubsets);
        }

        // Add in the last element
        subsets.Add(set[set.Length - 1].ToString());
        subsets.Sort();

        Console.WriteLine(string.Join(Environment.NewLine, subsets));
Sapph
  • 6,118
  • 1
  • 29
  • 32
5

if all you need are combinations of the elements in your original list, you can transform the problem into the following: you have a bit array of size N, and you want to find all possible choices for the elements of the array. For example, if your original list is

a b c d e

then your array can be

0 1 0 0 0

which results in an output of

b

or the array can be

1 0 1 1 0

which returns

acd

this is a simple recursion problem that can be solved in an O(2^n) time

edit adding pseudo-code for recursion algorithm:

CreateResultSet(List<int> currentResult, int step)
{
    if (the step number is greater than the length of the original list)
    {
        add currentResult to list of all results
        return
    }
    else
    {
        add 0 at the end of currentResult
        call CreateResultSet(currentResult, step+1)

        add 1 at the end of currentResult
        call CreateResultSet(currentResult, step+1)
    }
}

for every item in the list of all results
display the result associated to it (i.e. from 1 0 1 1 0 display acd)
vlad
  • 4,748
  • 2
  • 30
  • 36
  • This is right and i was thinking orginaly of some sort of binary switch to turn on each combo but im not sure how to go about coding it – Crash893 Feb 17 '11 at 02:01
2

This will work with any collection. I modified @Sapp's answer a little

    static List<List<T>> GetSubsets<T>(IEnumerable<T> Set)
    {
        var set = Set.ToList<T>();

        // Init list
        List<List<T>> subsets = new List<List<T>>();

        subsets.Add(new List<T>()); // add the empty set

        // Loop over individual elements
        for (int i = 1; i < set.Count; i++)
        {
            subsets.Add(new List<T>(){set[i - 1]});

            List<List<T>> newSubsets = new List<List<T>>();

            // Loop over existing subsets
            for (int j = 0; j < subsets.Count; j++)
            {
                var newSubset = new List<T>();
                foreach(var temp in subsets[j])
                    newSubset.Add(temp);

                newSubset.Add(set[i]);


                newSubsets.Add(newSubset);
            }

            subsets.AddRange(newSubsets);
        }

        // Add in the last element
        subsets.Add(new List<T>(){set[set.Count - 1]});
        //subsets.Sort();

        return subsets;
    }

**And then if I have a set of strings I will use it as:

enter image description here

Community
  • 1
  • 1
Tono Nam
  • 34,064
  • 78
  • 298
  • 470
1

Here is some code I made. It constructs a list of all possible strings from an alphabet, of lengths 1 to maxLength: (in other words, we are calculating the powers of the alphabet)

  static class StringBuilder<T>
  {
    public static List<List<T>> CreateStrings(List<T> alphabet, int maxLength)
    {
      // This will hold all the strings which we create
      List<List<T>> strings = new List<List<T>>();

      // This will hold the string which we created the previous time through
      // the loop (they will all have length i in the loop)
      List<List<T>> lastStrings = new List<List<T>>();
      foreach (T t in alphabet)
      {
        // Populate it with the string of length 1 read directly from alphabet
        lastStrings.Add(new List<T>(new T[] { t }));
      }

      // This holds the string we make by appending each element from the
      // alphabet to the strings in lastStrings
      List<List<T>> newStrings;

      // Here we make string2 for each length 2 to maxLength
      for (int i = 0; i < maxLength; ++i)
      {
        newStrings = new List<List<T>>();
        foreach (List<T> s in lastStrings)
        {
          newStrings.AddRange(AppendElements(s, alphabet));
        }
        strings.AddRange(lastStrings);
        lastStrings = newStrings;
      }

      return strings;
    }

    public static List<List<T>> AppendElements(List<T> list, List<T> alphabet)
    {
      // Here we just append an each element in the alphabet to the given list,
      // creating a list of new string which are one element longer.
      List<List<T>> newList = new List<List<T>>();
      List<T> temp = new List<T>(list);
      foreach (T t in alphabet)
      {
        // Append the element
        temp.Add(t);

        // Add our new string to the collection
        newList.Add(new List<T>(temp));

        // Remove the element so we can make another string using
        // the next element of the alphabet
        temp.RemoveAt(temp.Count-1);
      }
      return newList;
    }
  }
Ken Wayne VanderLinde
  • 18,915
  • 3
  • 47
  • 72
  • I had similar code in my original answer, but it turns out the asker wasn't clear originally and this is not the solution he needs. – Sapph Feb 16 '11 at 23:39
1

something on the lines of an extended while loop :

<?

$testarray[0] = "a";
$testarray[1] = "b";
$testarray[2] = "c";
$testarray[3] = "d";
$testarray[4] = "e";


$x=0;
$y = 0;
while($x<=4) {

$subsetOne[$x] .= $testarray[$y];
$subsetOne[$x] .= $testarray[$x];

$subsetTwo[$x] .= $testarray[$y];
$subsetTwo[$x] .= $subsetOne[$x];

$subsetThree[$x] = str_replace("aa","ab",$subsetTwo[$x]);

$x++;
}



?>
Dan J
  • 16,319
  • 7
  • 50
  • 82
kyle04
  • 11
  • 2