Files
teams/teams.c
2024-07-30 11:25:33 -04:00

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;
}