// Ordenamiento por selección que no sabe qué ordena, con la misma firma que qsort.
#include <stdio.h>
#include <string.h>

#define INT_COUNT 6
#define TRIP_COUNT 3

typedef int (*Compare)(const void *, const void *);

typedef struct {
    char route[12];
    int passengers;
} Trip;

void swap_bytes(unsigned char *a, unsigned char *b, size_t size) {
    for (size_t i = 0; i < size; i++) {
        unsigned char saved = a[i];
        a[i] = b[i];
        b[i] = saved;
    }
}

void any_sort(void *base, size_t count, size_t size, Compare compare) {
    unsigned char *bytes = base;
    for (size_t i = 0; i < count; i++) {
        size_t smallest = i;
        for (size_t j = i + 1; j < count; j++) {
            if (compare(bytes + j * size, bytes + smallest * size) < 0) {
                smallest = j;
            }
        }
        if (smallest != i) {
            swap_bytes(bytes + i * size, bytes + smallest * size, size);
        }
    }
}

int compare_ints(const void *first, const void *second) {
    int a = *(const int *) first;
    int b = *(const int *) second;
    return (a > b) - (a < b);
}

int compare_routes(const void *first, const void *second) {
    const Trip *a = first;
    const Trip *b = second;
    return strcmp(a->route, b->route);
}

int main(void) {
    int grades[INT_COUNT] = {14, 9, 20, 11, 9, 17};
    any_sort(grades, INT_COUNT, sizeof(grades[0]), compare_ints);
    for (int i = 0; i < INT_COUNT; i++) {
        printf("%d ", grades[i]);
    }
    printf("\n");

    Trip trips[TRIP_COUNT] = {{"Chosica", 18}, {"Ate", 9}, {"Callao", 25}};
    any_sort(trips, TRIP_COUNT, sizeof(trips[0]), compare_routes);
    for (int i = 0; i < TRIP_COUNT; i++) {
        printf("%s %d\n", trips[i].route, trips[i].passengers);
    }
    return 0;
}
