aka_eu said:
I have this problem.
I'm trying to get all the valid combination C(N,K) that pass one
condition.
For example C(5,3) can use in any combination this numbers {1,2,3,4,5}
But let's say that I have the limitations that these pair of numbers
cannot be part of the same combination {2,3} and {4,5}
So the right soolution are only :
{1,2,4}
{1,2,5}
{1,3,4}
{1,3,5}
My sollution for a test of C(20,13) with 7 pairs of numbers took me
about 25s, but it's too much for my needs.
Does anyone has a better algorithm ?
Maybe. (I'll post some code below.) I pulled out my probability and
statistics textbook from years ago. If there was a quick answer in there, I
didn't find it.
The first problem I see is how to quickly determine if {2,3}or {4,5} is in
the generated set:
{1,2,3}
{1,2,4}
{1,2,5}
{1,3,4}
{1,3,5}
{1,4,5}
{2,3,4}
{2,3,5}
{2,4,5}
{3,4,5}
{2,3} could be the 2nd & 3rd values or the 1st & 2nd. This gets worse for
C(20,13). {14,15} could be in six(?) different positions. This would
suggest fixing the positions, i.e., 2 always in the 2nd position:
{1,2,3,0,0}
{1,2,0,4,0}
{1,2,0,0,5}
{1,0,3,4,0}
{1,0,3,0,5}
{1,0,0,4,5}
{0,2,3,4,0}
{0,2,3,5,0}
{0,2,0,4,5}
{0,0,3,4,5}
Unfortunately, this would also cause unnecessary additional looping to
search for valid non-zero values, but it has the advantage of easily
determining if {2,3} or {4,5} is in the set since the positions are fixed.
So, can we get the benefits of this without the disadvantages? Yes. We can
use one array with fixed positions as indicators, and another array for the
set of values:
{1,2,3} {1,1,1,0,0}
{1,2,4} {1,1,0,1,0}
{1,2,5} {1,1,0,0,1}
{1,3,4} {1,0,1,1,0}
{1,3,5} {1,0,1,0,1}
{1,4,5} {1,0,0,1,1}
{2,3,4} {0,1,1,1,0}
{2,3,5} {0,1,1,0,1}
{2,4,5} {0,1,0,1,1}
{3,4,5} {0,0,1,1,1}
Now we have one array with the valid values and a quick way to exclude
unwanted sets. This code has an #if directive that allows you to see the
entire computation or just the valid sets (change from '#if 0' to '#if 1').
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 5
#define K 3
unsigned long val[K];
unsigned char ind[N+1]; /* "boolean" */
void cnk(void)
{
unsigned long p1,p2,p3;
unsigned long i;
unsigned char exclude;
memset(ind,0,N);
for(p1=1;p1<=N;p1++)
{
val[0]=p1;
ind[p1]=1;
for(p2=p1+1;p2<=N;p2++)
{
val[1]=p2;
ind[p2]=1;
for(p3=p2+1;p3<=N;p3++)
{
exclude=0;
val[2]=p3;
ind[p3]=1;
#if 0
/* change 0 to 1 for full complete info */
for(i=0;i<K;i++)
printf("%ld ",val
);
printf(" ");
for(i=0;i<N;i++)
printf("%d ",ind);
if(ind[2]&&ind[3])
printf("*");
if(ind[4]&&ind[5])
printf("*");
printf("\n");
#else
/* only print reduced sets */
if(ind[2]&&ind[3]) /* eliminate {2,3} */
exclude=1;
if(ind[4]&&ind[5]) /* eliminate {4,5} */
exclude=1;
if(!exclude)
{
for(i=0;i<K;i++)
printf("%ld ",val);
printf("\n");
}
#endif
ind[p3]=0; /* clear indicator */
}
ind[p2]=0; /* clear indicator */
}
ind[p1]=0; /* clear indicator */
}
}
int main(void)
{
cnk();
return(EXIT_SUCCESS);
}
HTH,
Rod Pemberton