170 lines
3.5 KiB
C
170 lines
3.5 KiB
C
#include <math.h>
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
|
|
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;
|
|
}
|