// La búsqueda genera; un callback decide qué se hace con cada resultado.
#include <stdio.h>

#define SHOWN 3
#define COUNTED 5

typedef void (*OnPermutation)(const int *items, int n, void *context);

void swap(int *a, int *b) {
    int saved = *a;
    *a = *b;
    *b = saved;
}

void explore(int *items, int n, int position, OnPermutation visit, void *context) {
    if (position == n) {
        visit(items, n, context);
        return;
    }
    for (int i = position; i < n; i++) {
        swap(&items[position], &items[i]);
        explore(items, n, position + 1, visit, context);
        swap(&items[position], &items[i]);
    }
}

void print_permutation(const int *items, int n, void *context) {
    (void) context;
    for (int i = 0; i < n; i++) {
        printf("%d ", items[i]);
    }
    printf("\n");
}

typedef struct {
    int total;
    int first_is_smaller;
} Tally;

void count_permutation(const int *items, int n, void *context) {
    Tally *tally = context;
    tally->total++;
    if (items[0] < items[n - 1]) {
        tally->first_is_smaller++;
    }
}

int main(void) {
    int few[SHOWN] = {1, 2, 3};
    explore(few, SHOWN, 0, print_permutation, NULL);

    int more[COUNTED] = {1, 2, 3, 4, 5};
    Tally tally = {0, 0};
    explore(more, COUNTED, 0, count_permutation, &tally);
    printf("%d permutaciones, en %d el primero es menor que el último\n",
           tally.total, tally.first_is_smaller);
    return 0;
}
