#include "rotagen.h" #include #include #include #define POOL_SIZE 0x1000 /* Hard-coded test data. */ static const char *people[] = { "alice", "bob", "charlie", "dave", "eve", "fred", "george", }; static const int num_people = sizeof(people) / sizeof(people[0]); static const char *jobs[] = { "washing dishes", "putting away", "wiping surfaces", }; static const int num_jobs = sizeof(jobs) / sizeof(jobs[0]); static const char *slots[] = { "mon", "tue", "wed", "thu", "fri", "sat", "sun", }; static const int num_slots = sizeof(slots) / sizeof(slots[0]); static const struct constraint constraints[] = { { .person = 0, .type = JOB_EXEMPTION_CONSTRAINT, .object = { .job = 2 }, }, { .person = 1, .type = SLOT_EXEMPTION_CONSTRAINT, .object = { .slot = 4 }, }, }; static const int num_constraints = sizeof(constraints) / sizeof(constraints[0]); static uint8_t pool[POOL_SIZE]; static uint8_t *free_ptr; static void *pool_alloc(int size) { if (free_ptr + size > pool + POOL_SIZE) return NULL; void *ptr = free_ptr; free_ptr += size; return ptr; } int main(void) { free_ptr = &pool[0]; unsigned seed; struct timeval now; if (gettimeofday(&now, NULL) == 0) { seed = now.tv_usec; } else { fprintf(stderr, "Warning: failed to get time of day to seed random number " "generation; falling back to hard-coded seed.\n"); seed = 0xdeadbeef; } srand(seed); struct slot_result *rota = pool_alloc(num_slots * sizeof(struct slot_result)); if (rota == NULL) { fprintf(stderr, "Fatal error: memory pool exhausted in %s().\n", __func__); exit(1); } generate_rota(rota); print_rota(rota); return 0; } void generate_rota(struct slot_result *rota_out) { for (int slot = 0; slot < num_slots; ++slot) { do { for (int j = 0; j < num_jobs; ++j) { struct allocation *allocation = &rota_out[slot].allocations[j]; do { generate_allocation(slot, j, allocation); } while (!satisfies_allocation_constraints(allocation)); } } while (!satisfies_slot_constraints(&rota_out[slot])); } } void generate_allocation(int slot, int job, struct allocation *allocation_out) { allocation_out->slot = slot; allocation_out->job = job; allocation_out->person = rand() % num_people; } bool satisfies_allocation_constraints(const struct allocation *allocation) { for (int i = 0; i < num_constraints; ++i) { if (allocation->person != constraints[i].person) continue; switch (constraints[i].type) { case JOB_EXEMPTION_CONSTRAINT: if (allocation->job == constraints[i].object.job) return false; break; case SLOT_EXEMPTION_CONSTRAINT: if (allocation->slot == constraints[i].object.slot) return false; break; default: fprintf(stderr, "Warning: unhandled constraint type %d in %s()", constraints[i].type, __func__); break; } } return true; } bool satisfies_slot_constraints(const struct slot_result *result) { for (int i = 0; i < num_jobs; ++i) { for (int j = i + 1; j < num_jobs; ++j) { if (result->allocations[i].person == result->allocations[j].person) return false; } } return true; } void print_rota(const struct slot_result *rota) { for (int slot = 0; slot < num_slots; ++slot) { for (int job = 0; job < num_jobs; ++job) { printf("%s\t%s\t%s\n", job == 0 ? slots[slot] : " ", jobs[job], people[rota[slot].allocations[job].person]); } } }