diff options
author | Squibid <me@zacharyscheiman.com> | 2024-07-30 11:21:40 -0400 |
---|---|---|
committer | Squibid <me@zacharyscheiman.com> | 2024-07-30 11:25:33 -0400 |
commit | bb52f5a54acc89afb936eda41daa473f15913a7b (patch) | |
tree | 15e2e659cc58fb64d64a2efbd5d35856344638d4 /teams.c | |
download | teams-bb52f5a54acc89afb936eda41daa473f15913a7b.tar.gz teams-bb52f5a54acc89afb936eda41daa473f15913a7b.tar.bz2 teams-bb52f5a54acc89afb936eda41daa473f15913a7b.zip |
Diffstat (limited to '')
-rw-r--r-- | teams.c | 169 |
1 files changed, 169 insertions, 0 deletions
@@ -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; +} |