5

I want to make simple sorting algorithm.

given the input "abcde", I would like the output below. could you tell me the algorithm for that?

arr[0] = "a"
arr[1] = "ab"
arr[2] = "ac"
arr[3] = "ad"
arr[4] = "ae"
arr[5] = "abc"
arr[6] = "abd"
arr[7] = "abe"
...
arr[n] = "abcde"

arr[n+1] = "b"
arr[n+2] = "bc"
arr[n+3] = "bd"
arr[n+4] = "be"
arr[n+5] = "bcd"
arr[n+5] = "bce"
arr[n+5] = "bde"
...
arr[n+m] = "bcde"
...
...
Coral Doe
  • 1,925
  • 3
  • 19
  • 36

3 Answers3

7

An algorithm for "generating Power Set" from an array is what you are looking for. You can try Google or some other search engine to find the algorithm that best fits your needs.

rahmivolkan
  • 407
  • 2
  • 9
  • 8
    +1 cause sometimes people feel that they need to google for something but do not know the name of the algorithm. – Muxecoid Mar 24 '10 at 11:24
6

In C++ given the following routine:

template <typename Iterator>
bool next_combination(const Iterator first, Iterator k, const Iterator last)
{
   /* Credits: Mark Nelson http://marknelson.us */
   if ((first == last) || (first == k) || (last == k))
      return false;
   Iterator i1 = first;
   Iterator i2 = last;
   ++i1;
   if (last == i1)
      return false;
   i1 = last;
   --i1;
   i1 = k;
   --i2;
   while (first != i1)
   {
      if (*--i1 < *i2)
      {
         Iterator j = k;
         while (!(*i1 < *j)) ++j;
         std::iter_swap(i1,j);
         ++i1;
         ++j;
         i2 = k;
         std::rotate(i1,j,last);
         while (last != j)
         {
            ++j;
            ++i2;
         }
         std::rotate(k,i2,last);
         return true;
      }
   }
   std::rotate(first,k,last);
   return false;
}

You can then proceed to do the following:

std::string s = "abcde";
for(std::size_t i = 1; i != s.size(); ++i)
{
   do
   {
      std::cout << std::string(s.begin(),s.begin() + i) << std::endl;
   }
   while(next_combination(s.begin(),s.begin() + i,s.end()));
}

Note: That you should expect to see 2^n-1 combinations, where n is the length of the array or string.

  • The website you cited does not appear to contain this program. – Potatoswatter Mar 24 '10 at 18:07
  • 7
    you should try a little harder: http://marknelson.us/2002/03/01/next-permutation on the page search for the term: "next_combination" –  Mar 24 '10 at 20:38
  • @Beh: Incorrect. I put next_combination in the search bar, it auto-completed, and returned no results http://marknelson.us/index.php?submit.x=0&submit.y=0&s=next_combination . I suspect you used Google. In any case, that page *doesn't* contain that program, there are only comments with links to various similar programs. The closest I see to an explanation is http://www.codeguru.com/cpp/cpp/algorithms/combinations/article.php/c5117/ but it doesn't have this particular code. Having reposted someone's code, you should provide clearer credits. – Potatoswatter Apr 07 '10 at 20:48
5

You are describing a power set. Here is some C++ code:

#include <vector>
#include <string>
#include <algorithm>
#include <functional>
using namespace std;

vector< string > string_powerset( string const &in ) {
    vector< string > result(1); // start output with one empty string
    result.reserve( 1 << in.size() ); // output size = 2^( in.size() )
    if ( result.capacity() != 1<<in.size() ) throw range_error( "too big" );

    for ( string::const_iterator it = in.begin(); it != in.end(); ++ it ) {
        size_t middle = result.size(); // duplicate what we have so far
        result.insert( result.end(), result.begin(), result.end() );

          // append current character onto duplicated output
        for_each( result.begin() + middle, result.end(),
           bind2nd( mem_fun_ref( &string::push_back ), * it ) );
    }
    return result;
}

Tested working :v) . The range check isn't the best, but whatever.

This code will tend to overflow, due to the exponential growth of the powerset, so you should only pass it short strings. The other posted answer avoids this problem by generating and returning one string at a time. However, this is easier to understand, and using a far larger and more confusing piece of code would be premature optimization unless you actually have an overflow problem.

EDIT: I wrote up a next_subset answer, and it looks nothing like Ben's.

Community
  • 1
  • 1
Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
  • 1
    I voted you up, because you make nice use of STL. But there are some things i would critize, but these are style issues. First, `using namespace std` is not a good Idea. Second, using the shift operator for power of 2 is a bit unclear. Third, why `string const & in` instead of `const string & in` (I have never seen that)? – Björn Pollex Mar 25 '10 at 09:10
  • 1. I felt I earned some laziness by fixing the question and writing all this code. OP doesn't strike me as likely to have large-codebase issues. This isn't a header file. 2. So I commented on it and also noted dismay on the overflow situation. 3. My `const` style is more uniform. `const` attaches to the *preceding* identifier or modifier, unless `const` is the first token of the type. I avoid the special case. Also, saying `string` first "gets down to business faster." – Potatoswatter Mar 25 '10 at 11:14
  • 1
    For the record, this answer now has 3 upvotes and 3 downvotes. No downvoter has left a comment. – Potatoswatter Apr 07 '10 at 20:40
  • I upvoted you for the reason they downvoted. I myself use style presented by you, and if someone tells me that he never saw this before I just don't know what to say. – There is nothing we can do Apr 13 '10 at 13:39