Ejemplo n.º 1
0
Archivo: enum.c Proyecto: rdebath/sgt
void listcomb_from_index(int *array, int n, int k, int index)
{
    int ret = 0;
    int i, j, nck;

    /* nck equals n choose k; we adjust it gradually as we alter n and k. */
    nck = comb_count(n, k);

    j = 0;
    while (k > 0) {
	/*
	 * The element here is j in the first (n-1 choose k-1)
	 * positions, otherwise more than j.
	 * 
	 * FIXME: it would be nice if we could find a closed form
	 * for this and replace the while loop with some sort of
	 * binary search, thus rendering the algorithm O(k) rather
	 * than O(n). May not be possible, but worth thinking
	 * about.
	 */
	while (index >= nck * k / n) {
	    index -= nck * k / n;
	    nck = nck * (n-k) / n;
	    n--;
	    j++;
	}

	nck = nck * k / n;
	k--;
	*array++ = j++;
	n--;
    }
}
Ejemplo n.º 2
0
Archivo: enum.c Proyecto: rdebath/sgt
void setcomb_from_index(char *array, int n, int k, int index)
{
    int i, nck;

    /* nck equals n choose k; we adjust it gradually as we alter n and k. */
    nck = comb_count(n, k);

    while (k > 0) {
	if (index < nck * k / n) {
	    /*
	     * First element is here.
	     */
	    *array = 1;
	    nck = nck * k / n;
	    k--;
	} else {
	    /*
	     * It isn't.
	     */
	    *array = 0;
	    index -= nck * k / n;
	    nck = nck * (n-k) / n;
	}
	array++;
	n--;
    }

    /*
     * Fill up the remainder of the array with zeroes.
     */
    while (n-- > 0)
	*array++ = 0;
}
Ejemplo n.º 3
0
Archivo: enum.c Proyecto: rdebath/sgt
int setcomb_to_index(char *array, int n, int k)
{
    int ret = 0;
    int i, nck;

    /* nck equals n choose k; we adjust it gradually as we alter n and k. */
    nck = comb_count(n, k);

    while (1) {
	if (k == 0)
	    return ret;		       /* only one position now */

	if (*array) {
	    /*
	     * First element found.
	     */
	    nck = nck * k / n;
	    k--;
	} else {
	    /*
	     * First element not found, meaning we have just
	     * skipped over (n-1 choose k-1) positions.
	     */
	    ret += nck * k / n;
	    nck = nck * (n-k) / n;
	}
	array++;
	n--;
    }
}
void comb(int list[],int list_size, int start, int count)
{
	int i;

	if (count == list_size-1) {
		for(i=0; i<3; i++){
			printf("%c",list[i]);
		}
	}

	for (i=start; i<list_size; i++) {
		comb_count (list, list_size, start, i);
	}
}
Ejemplo n.º 5
0
Archivo: enum.c Proyecto: rdebath/sgt
int listcomb_to_index(int *array, int n, int k)
{
    int ret = 0;
    int i, j, nck;

    /* nck equals n choose k; we adjust it gradually as we alter n and k. */
    nck = comb_count(n, k);

    j = 0;
    while (k > 0) {
	/*
	 * If the element here is not j, we must skip over (n-1
	 * choose k-1) positions in which it is.
	 * 
	 * FIXME: it would be nice if we could find a closed form
	 * for this and replace the while loop with some sort of
	 * binary search, thus rendering the algorithm O(k) rather
	 * than O(n). May not be possible, but worth thinking
	 * about.
	 */
	while (j++ < *array) {
	    ret += nck * k / n;
	    nck = nck * (n-k) / n;
	    n--;
	}

	/*
	 * Now we've found an element, so decrement both n and k.
	 */
	nck = nck * k / n;
	k--;
	array++;
	n--;
    }

    return ret;
}
Ejemplo n.º 6
0
Archivo: enum.c Proyecto: rdebath/sgt
void test_setcomb(int n)
{
    char a1[COMB_NMAX], a2[COMB_NMAX];
    int indices[COMB_NMAX+1];
    int i, j, k, index;

#ifndef QUIET
    printf("setcomb round-trip index tests, n=%d\n", n);
#endif

    /*
     * Enumerate all 2^n possible subsets of {0,...,n-1}, and check
     * that setcomb_to_index() translates each one correctly to a
     * combination index, that setcomb_from_index() translates each
     * one correctly back again, and that the indices are in the
     * expected order.
     */
    for (i = 0; i <= n; i++)
	indices[i] = comb_count(n, i) - 1;

    for (i = 0; i < (1 << n); i++) {

	k = 0;
	for (j = 0; j < n; j++) {
	    a1[j] = (i & (1 << (n-1-j))) != 0;
	    k += a1[j] != 0;
	}

	index = setcomb_to_index(a1, n, k);
	setcomb_from_index(a2, n, k, index);

#ifndef QUIET
	for (j = 0; j < n; j++)
	    putchar(a1[j] ? '#' : '-');
	printf(" (k =%3d) ->%5d -> ", k, index);
	for (j = 0; j < n; j++)
	    putchar(a2[j] ? '#' : '-');
	putchar('\n');
#endif

	EQ(index, indices[k]);
	indices[k]--;

	EQ(memcmp(a1, a2, n), 0);
    }

    /*
     * Now enumerate using setcomb_first() and setcomb_next(), and
     * verify that we get the expected number of combinations, that
     * each combination is valid, and that the indices are also as
     * expected.
     */
    for (k = 0; k <= n; k++) {
	index = 0;

#ifndef QUIET
	printf("setcomb enumeration tests, n=%d, k=%d\n", n, k);
#endif

	setcomb_first(a1, n, k);
	do {
	    for (i = j = 0; j < n; j++)
		i += a1[j] != 0;
	    EQ(i, k);

	    i = setcomb_to_index(a1, n, k);

#ifndef QUIET
	    for (j = 0; j < n; j++)
		putchar(a1[j] ? '#' : '-');
	    printf(" ->%5d\n", i);
#endif

	    EQ(index, i);
	    index++;
	} while (setcomb_next(a1, n, k));

	i = comb_count(n, k);
	EQ(index, i);
    }
}