Thomas said:
Hello all,
I have an array of values which I would like to generate all possible
combinations for. And example would be the values "a,b,c".
I hope you mean "abc" or {'a','b','c'}, otherwise some more complex
string handling will be required.
This would
produce the following:
a
ab
abc
ac
b
bc
c
what about cba, ba, cb, bca, etc? I assume you want only combinations
in which the output elements are in the order they appeared in the
input. I also assume that duplicate detection isn't required, meaning
that "aaa" => { "a", "a", "a", "aa", "aa", "aa", "aaa" }.
Does anybody know of the algorithm to produce this? I've seen the topic
discussed, but never for strings or anything of the such. Most discussion
is regarding calculating the number of combinations...which I don't care
about.
There are two common ways to design this type of algorith. One way is
to define a rule for ordering the elements of the set you wish to
produce: once you work that out it is often easy to define a production
rule which will emit the successor to any given element.
The other way is to take an easy-to-calculate series and define a
one-to-one mapping from that series to the desired output. I've used
this method here.
This C99 code will emit what you seem to be asking for, although not in
the order you showed above:
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
void
print_combos ( size_t numelems,
const char *input
)
{
char outbuf[numelems + 1];
size_t idx;
// selector is an expensive implementation of a numelems-bit binary
// integer.
bool selector[numelems];
// We want to start at zero
memset(selector, false, numelems);
for (;
{
// Implement binary increment with overflow detection
bool carry;
idx = numelems;
do
{
--idx;
carry = selector[idx];
selector[idx] = !selector[idx];
} while (carry && (idx > 0));
// carry will only be true if the preceding increment overflowed
if (carry)
break;
// now copy the selected elements into the output buffer
size_t outpos = 0;
for (idx = 0; idx < numelems; ++idx)
if (selector[idx])
outbuf[outpos++] = input[idx];
// NUL-terminate it
outbuf[outpos] = '\0';
// and print it
puts(outbuf);
}
}
C90-fication is left as an exercise for the interested reader...