2

I'm writing some code and ended up with this problem. I have N products and I have to form all possible combinations of these products, form a product catalog and find some properties, like price. In order to do this I have to form the catalog of products from the given products (exhaustively, but no duplicates allowed). Is there a standardized algorithm for doing this? Note that the catalogs can contain any positive number of products.

Iterator
  • 20,250
  • 12
  • 75
  • 111
Malice
  • 1,457
  • 16
  • 32
  • permutation = order matters (an ordered list). combination = order doesn't matter (a set). – Karoly Horvath Aug 29 '11 at 12:00
  • ok . Then I guess this is combination – Malice Aug 29 '11 at 12:01
  • If it's a combination you can just do: `for i = 1 to 2^N` and use bit hax... I think... – flight Aug 29 '11 at 12:05
  • 2
    Voting to close. Problem's underspecified so we can't tell what you are trying to do (generate all permutations? all combinations? of size K?). You will have to be a lot more specific. Also finding all the permutations of a catalog of size 100 would take so long, that the universe would end before you finished. You probably don't want that if your catalog is larger than 10 items. I assume your catalog probably has something like hundreds of items. If what you want are K-combinations, those scale like N^K. e.g. printing out all 10-sets would take longer than the age of the universe. – ninjagecko Aug 29 '11 at 12:23
  • `any positive number` is much too vague. For very small numbers, the problem is solvable in memory, but soon it isn't. `exhaustively` is a word, you surely don't like to hear in that context. See yi_H's answer, and think about 2^65 combinations for 65 elements. – user unknown Aug 29 '11 at 13:23
  • Well now i'm feeling foolish askin this question, i really had no idea the combination(not permutuation) was goin to be so HUGE . And considering the fact that i need all combinations (not just of size k) makes it even more difficult . may be there's a easy way around , i must see to it – Malice Aug 29 '11 at 15:18
  • @quasiverse Where did you learn the bit-hack combination method? I [independently invented it](http://stackoverflow.com/a/3689817/57611) but I wonder how long it's been around. – ErikE Aug 16 '12 at 22:31
  • @ErikE Well... I learnt it from various algorithm competitions and related preparations. E.g. [topcoder.com's algorithm tutorials](http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=bitManipulation) – flight Aug 17 '12 at 08:25

4 Answers4

4

Combinations can be represented by a bit-vector. If a bit is set, the element is present in the combination.

So you simply have to enumarte all numbers from 1 to 2^N-1 (from 0000001, last element present till 1111111, all elements present), and will represent a possible combination.

Karoly Horvath
  • 94,607
  • 11
  • 117
  • 176
  • I'm using integers (as an index into array as of now) as the products . Is there a way to proceed from this set up rather than writing up new code :-( – Malice Aug 29 '11 at 12:06
  • well, if you don't want to decode the numbers you could implement your own binary incrementer (each index in the array is a binary digit). You could also use some clever gray code generator to enumerate all numbers http://en.wikipedia.org/wiki/Gray_code – Karoly Horvath Aug 29 '11 at 12:15
  • Ya i've already written a lot and reimplementing will be timeconsumin – Malice Aug 29 '11 at 12:37
  • @Malice: You should show us the code, if you want us reuse it. – user unknown Aug 29 '11 at 13:27
  • @Karoly where did you learn this method? I [independently invented it](http://stackoverflow.com/a/3689817/57611) but I wonder how long it's been around. – ErikE Aug 16 '12 at 22:31
2

A naive implementation to print all combination of characters from a give string:

void print_combination(char* str, char* buffer, int len, int num, int pos)                                                                 
{
  if(num == 0)
  {
    std::cout << buffer << std::endl;
    return;
  }

  for(int i = pos; i < len - num + 1; ++i)
  {
    buffer[num - 1] = str[i];
    print_combination(str, buffer, len, num - 1, i + 1);
  }
}

int main()
{
  char str[] = "abcde";
  char buffer[6];
  for(auto i = 1u; i <= sizeof(str); ++i)
  {
    buffer[i] = '\0';
    print_combination(str, buffer, 5, i, 0);
  }
}

Quite simple but may have performance problem. Take it if it could help.

If you're looking for permutation(I can't tell from your description), I implemented the algorithm in The Art of Computer Programming:

template <typename Iter>                                                                                                                   
bool next_permutation(Iter start, Iter end)
{
  if(start == end)
    return false;

  Iter i = start + 1;
  if(i == end)
    return false;

  i = end - 1;

  while(true)
  {
    Iter ii = i;
    --i;
    if(*i < *ii)
    {
      Iter j = end;
      while(*i >= *--j);
      std::iter_swap(i, j);
      std::reverse(ii, end);
      return true;
    }
    if(i == start)
    {
      std::reverse(start, end);
      return false;
    }
  }
}

int main()
{
  char str1[] = "abcde";
  do
  {
    std::cout << str1 << std::endl;
  } while(next_permutation(&str1[0], &str1[5]));
}

It's quite efficient and C++ stl algorithm uses the same algorithm.

Mu Qiao
  • 6,941
  • 1
  • 31
  • 34
2

You can do this in python, using itertools.combinations in following way:

import itertools

products = ['p1', 'p2', 'p3', 'p4']
for L in range(1, len(products)+1):
      for subset in itertools.combinations(products, L):
              print(subset)

what gives as result:

('p1',)
('p2',)
('p3',)
('p4',)
('p1', 'p2')
('p1', 'p3')
('p1', 'p4')
('p2', 'p3')
('p2', 'p4')
('p3', 'p4')
('p1', 'p2', 'p3')
('p1', 'p2', 'p4')
('p1', 'p3', 'p4')
('p2', 'p3', 'p4')
('p1', 'p2', 'p3', 'p4')

Solution inspired by this answer of @dan-h.

Community
  • 1
  • 1
Grzegorz Wierzowiecki
  • 10,545
  • 9
  • 50
  • 88
1

The first few sections of The Art of Computer Programming, vol. 3, Sorting and Searching discusses Inversion and Permutation (of a set and multisets) in great detail. In this case it is important to dabble in theory a bit, see what's out there. The code will follow, but if this is "leisure time coding", why not do it including "leisure time theory" as well? Betcha it's going to be cool, you'll know the whats but you'll also know the whys!

Dervin Thunk
  • 19,515
  • 28
  • 127
  • 217