initial commit
This commit is contained in:
169
teams.c
Normal file
169
teams.c
Normal file
@ -0,0 +1,169 @@
|
||||
#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;
|
||||
}
|
Reference in New Issue
Block a user