#include #include #include #include #include #include #include typedef struct Person { char *name; struct Person *opponent; } Person; static void die(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); if (fmt[0] && fmt[strlen(fmt)-1] == ':') { fputc(' ', stderr); perror(NULL); } else fputc('\n', stderr); exit(1); } /** * @brief get number of substr in str * * @param haystack str to search * @param needle substr * @return number of substr in str */ static inline int numsubstr(const char *haystack, const char *needle) { int i = 0; const char *tmp = haystack; while((tmp = strstr(tmp, needle))) { i++; tmp++; } return i; } /** * @brief cleanup people ptrs * * @param p pointer to person * @param len number of people in p */ void destroypeopleptr(Person *p, size_t num) { int i; for (i = 0; i < num; i++) if (p[i].name && p[i].name == NULL) free(p[i].name); free(p); } int main(int argc, char *argv[]) { int j, i, l, t, c, a, r, min, numteams, numpeople, peopleperteam; Person *people, **teams; /* seed random number generator */ srand(time(NULL)); /* get number of people declared and allocate enough space for them */ for (i = numpeople = 0; i < argc; i++) numpeople += numsubstr(argv[i], "-p"); /* allocate space for all people */ people = calloc(numpeople, sizeof(Person)); /* collect people and team numbers */ i = 0; while ((c = getopt(argc, argv, "p:t:")) != -1) { switch (c) { case 'p': people[i++] = (Person){ .name = optarg, .opponent = NULL }; break; case 't': numteams = atoi(optarg); break; } } /* exit if there aren't enough people for the number of teams */ if (floor((double)numpeople / (double)numteams) < 1) die("%d people is not enough for %d teams", numpeople, numteams); /* allocate space for teams */ teams = calloc(numteams, sizeof(Person *)); /* calculate maximum number of people per team */ peopleperteam = floor(((double)numpeople / (double)numteams) + 0.5); /* allocate space for people in each team */ for (i = 0; i < numteams; i++) teams[i] = calloc(peopleperteam, sizeof(Person)); /* randomize array */ for (i = 0; i < numpeople; i++) { r = rand() / (RAND_MAX / numpeople); Person tmp = people[r]; people[r] = people[i]; people[i] = tmp; } /* sort people into teams */ for (i = j = l = min = 0; i < numpeople; i++) { if (l == peopleperteam) { if (j < numteams - 1) { j++; l = min; } else { /* resize arrays */ for (t = 0; t < numteams; t++) { Person *b = calloc(peopleperteam + 1, sizeof(Person)); for (a = 0; a < peopleperteam; a++) { b[a].name = teams[t][a].name; b[a].opponent = teams[t][a].opponent; } destroypeopleptr(teams[t], numpeople); teams[t] = b; b = NULL; } j = 0; l = min = peopleperteam++; } } /* assign person to team */ teams[j][l++] = people[i]; } /* print out teams */ for (i = 0; i < numteams; i++) { printf("team #%d:\n", i + 1); for (j = 0; j < peopleperteam; j++) if (teams[i][j].name) puts(teams[i][j].name); } /* cleanup */ destroypeopleptr(people, numpeople); for (i = 0; i < numteams; i++) free(teams[i]); free(teams); return 0; }