colloscope/algorithm.c

1090 lines
39 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "display.c"
bool is_equal_date(date d1, date d2) {
return (d1.hour == d2.hour && d1.day == d2.day && d2.month == d1.month && d2.year == d1.year);
}
int get_date_index(creneau* edt, int len_creneau, date d) {
// could be done in log(n), I know
// yields the 1st occurence of d in edt
int x = -1;
for(int i = 0; i < len_creneau; i++) {
x = date_dist(d, edt[i].date);
if(x >= 0) {
return i;
}
}
return -1;
}
array get_all_date_index(creneau* edt, int len_edt, date d) {
array arr;
arr.a = malloc(sizeof(int)*8);
arr.memlen = 8;
arr.len = 0;
int x = -1;
int halt = 0;
for(int i = 0; i < len_edt-halt; i++) {
x = date_dist(d, edt[i].date);
if(x == 0) {
arr.a[arr.len] = i;
arr.len++;
} else if(x > 0) {
halt = len_edt;
}
}
return arr;
}
int get_next_friday(creneau* edt, int len_creneau, date d) {
// could be done in log(n), I know again
int x = -1;
for(int i = 0; i < len_creneau; i++) {
x = date_dist(d, edt[i].date);
//printf("%d\n", x);
if(x >= 0 && (i == len_creneau-1 || date_dist(d, edt[i+1].date) - x > 1)) {
return i;
}
}
return -1;
}
int get_fst_offset(creneau* edt, date d) {
return (date_dist(edt[0].date, d));
}
bool is_allowed_MP2I(creneau* edt, int len_edt, int grp, date end) {
bool debug = false;
/* conditions (AND) :
0) Only 1 colle at a time
1) Alternate between physics and english
2) Pattern for math colles is exactly 3-1-3-1-...
3) Between 1 and 2 colles per week and per group (exclusing special colles such as Info)
4) Special colles (aka INFO) at least 1 every 6 weeks
*/
int end_id = get_next_friday(edt, len_edt, end); // index of first date that is later than end
if(end_id == -1) {
stats[4]++;
return true;
}
int offs = get_date_index(edt, len_edt, end);
//printf("EndId : %d\n", end_id);
// 0)
int id = 1;
while(id >= 0 && id < len_edt && is_equal_date(edt[offs+id].date, end)) {
if(str_equal(edt[offs+id].name, edt[offs].name)) {
if(debug) {
printf("Unable to duplicate colleur %s\n", edt[offs].name);
}
stats[0]++;
return false;
}
id++;
}
id = -1;
while(id >= 0 && id < len_edt && is_equal_date(edt[offs+id].date, end)) {
if(str_equal(edt[offs+id].name, edt[offs].name)) {
if(debug) {
printf("Unable to duplicate colleur %s\n", edt[offs].name);
}
stats[0]++;
return false;
}
id--;
}
// 1) PC/AGL alternance
int agl = 0;
int pc = 0;
char has_to_be = 'n'; // 'n' = not set, 'a' = AGL and 'p' = PC
for(int i = end_id-1; i >= 0; i--) {
//for(int i = -1; i >= 0; i--) {
if(i != end_id-1 && (i == 0 || (date_dist(edt[0].date, edt[i].date)%7 == 4 && date_dist(edt[0].date, edt[i+1].date)%7 != 4))) {
//printf("Checking AGL/PC...\n");
// currently pointed date is the last friday of the week
// since we are going down, friday <==> reset variables and check for conflicts
if(agl + pc != 1) {
if(debug) {
printf("Invalid number of english/physics colle at index %d for group %d (found %d)\n", i, grp, agl+pc);
}
stats[1]++;
return false;
} else if(has_to_be == 'p' && pc != 1) {
if(debug) {
printf("Wrong number of physics colle at index %d for group %d\n", i, grp);
}
stats[1]++;
return false;
} else if(has_to_be == 'a' && agl != 1) {
if(debug) {
printf("Wrong number of english colle at index %d for group %d\n", i, grp);
}
stats[1]++;
return false;
}
if(has_to_be == 'n') {
if(agl == 1) {
has_to_be = 'p';
} else {
has_to_be = 'a';
}
} else if(has_to_be == 'p') {
has_to_be = 'a';
} else {
has_to_be = 'p';
}
agl = 0;
pc = 0;
}
if(edt[i].group == grp && edt[i].mat == ENGLISH) {
agl += 1;
} if(edt[i].group == grp && edt[i].mat == PHYSICS) {
pc += 1;
}
}
// 2) Math colles
// version 2
/*
int math = 0;
int abort_2 = 0;
for(int i = end_id-1; i >= 0+abort_2*(end_id); i--) {
if(i == 0 || (date_dist(edt[0].date, edt[i].date)%7 == 4 && date_dist(edt[0].date, edt[i+1].date)%7 != 4)) {
abort_2 = 1;
if(n_colles[grp-1] == 3) {
if(math != 0) {
if(debug) {
printf("Invalid number of math colles at index %d for group %d (found %d)\n", i, grp, math);
}
stats[2]++;
return false;
}
} else {
if(math != 1) {
if(debug) {
printf("Invalid number of math colles at index %d for group %d (found %d)\n", i, grp, math);
}
stats[2]++;
return false;
}
}
}
if(edt[i].group == grp && edt[i].mat == MATH) {
math += 1;
}
}*/
int t = 0;
int math = 0;
int last_no_math = -1;
bool not_seen_empty = true;
for(int i = end_id-1; i >= 0; i--) {
if(i == 0 || (date_dist(edt[0].date, edt[i].date)%7 == 4 && date_dist(edt[0].date, edt[i+1].date)%7 != 4)) {
//if(i == 0 || i%16 == 15) {
t++;
if(math != 1 && math != 0) {
if(debug) {
printf("Invalid number of math colles at index %d for group %d (found %d)\n", i, grp, math);
}
stats[2]++;
return false;
} else if(math == 0) {
if(!not_seen_empty && last_no_math != -1 && last_no_math != 3) {
if(debug) {
printf("Invalid rotation of math colles at index %d for group %d\n", i, grp);
}
//rintf("--> %d <--\n", t);
stats[2]++;
return false;
}
last_no_math = 0;
not_seen_empty = false;
} else {
if(last_no_math > 3) {
if(debug) {
printf("Too many math colles at index %d for group %d\n", i, grp);
}
stats[2]++;
return false;
}
if(last_no_math == -1) {
last_no_math++;
}
last_no_math++;
}
math = 0;
}
if(edt[i].group == grp && edt[i].mat == MATH) {
math += 1;
}
}
if(last_no_math > 3) {
if(debug) {
printf("Too many math colles at index %d for group %d\n", 0, grp);
}
stats[2]++;
return false;
}
// 3) Count
int ncolles = 0;
for(int i = end_id-1; i >= 0; i--) {
if(i == 0 || (date_dist(edt[0].date, edt[i].date)%7 == 4 && date_dist(edt[0].date, edt[i+1].date)%7 != 4)) {
if(ncolles != 1 && ncolles != 2) {
//if(ncolles != n_colles[grp-1]) {
if(debug) {
printf("Invalid number of colles at index %d for group %d (found %d)\n", i, grp, ncolles);
}
stats[3]++;
return false;
}
ncolles= 0;
}
if(edt[i].group == grp) {
ncolles++;
}
}
// 4) Info
int inf = 0;
int last_no_inf = -1;
for(int i = end_id-1; i >= 0; i--) {
if(i == 0 || (date_dist(edt[0].date, edt[i].date)%7 == 4 && date_dist(edt[0].date, edt[i+1].date)%7 != 4)) {
if(inf != 0 && inf != 1) {
if(debug) {
printf("Invalid number of info colles at index %d for group %d\n", i, grp);
}
stats[4]++;
return false;
} else if(inf == 0) {
last_no_inf = 0;
} else if(last_no_inf > 5) {
if(debug) {
printf("Too few info colles at index %d for group %d\n", i, grp);
}
stats[4]++;
return false;
} else {
if(last_no_inf != -1) {
last_no_inf += 1;
}
}
inf = 0;
}
if(edt[i].group == grp && edt[i].mat == INFO) {
inf += 1;
}
}
return true;
}
/*
for(int i = end_id-1; i >= 0; i--) {
if(i == 0 || (date_dist(edt[0].date, edt[i].date)%7 == 4 && date_dist(edt[0].date, edt[i+1].date)%7 != 4)) {
// Check week
}
// Detect colles
}
*/
int heuristique_MP2I(creneau* edt,int len_edt, int grp, date end) {
/*
A - Both colles end at 7PM : -10
B - Having the same colleur two weeks in a row : -45
C - Having the same colleur at a 3w interval : -25
D - Having the same colleur at a 4w interval : -10
E - Two colles the same day : -20
F - Same date over 2 weeks : -20
*/
int end_id = get_next_friday(edt, len_edt, end); // index of first date that is later than end
if(end_id == -1) {
return 0;
}
int score = 0;
int halt = 0;
int remaining = 2;
creneau* temp = malloc(sizeof(creneau)*16);
int len_temp = 0;
//printf("EndId : %d\n", end_id);
// A - Colles 7PM (-10)
// Check for current week only
bool _7pm_1 = false;
bool _7pm_2 = false;
for(int i = end_id-1; i >= 0+halt; i--) {
if(i == 0 || (date_dist(edt[0].date, edt[i].date)%7 == 4 && date_dist(edt[0].date, edt[i+1].date)%7 != 4)) {
score -= 10*(_7pm_1 && _7pm_2);
halt = end_id-1;
}
if(edt[i].group == grp && edt[i].date.hour == 18) {
//printf("E\n");
_7pm_2 = _7pm_1;
_7pm_1 = true;
}
}
halt = 0;
len_temp = 0;
// B, C and D : same colleur 2/3/4times in a row (-45)
// 4-week check
remaining = 4;
for(int i = end_id-1; i >= 0+halt; i--) {
if(i == 0 || (date_dist(edt[0].date, edt[i].date)%7 == 4 && date_dist(edt[0].date, edt[i+1].date)%7 != 4)) {
remaining -= 1;
if(remaining == 0 || i == 0) {
bool b = false;
int dist = 0;
for(int j = 0; j < len_temp; j++) {
for(int k = j+1; k < len_temp; k++) {
b = str_equal(temp[j].name, temp[k].name);
if(b && !(str_equal(temp[j].name, ""))) {
dist = date_dist(temp[k].date, temp[j].date);
if(dist < 7) {
score -= 45;
} else if(dist < 14) {
score -= 20;
} else if(dist < 21) {
score -= 10;
}
}
}
}
halt = end_id-1;
}
}
if(edt[i].group == grp) {
temp[len_temp] = edt[i];
len_temp++;
}
}
halt = 0;
len_temp = 0;
// E - 2 colles the same day (-20)
// single-week check
for(int i = end_id-1; i >= 0+halt; i--) {
if(i == 0 || (date_dist(edt[0].date, edt[i].date)%7 == 4 && date_dist(edt[0].date, edt[i+1].date)%7 != 4)) {
if(len_temp >= 2) {
score -= 20*(temp[0].date.day == temp[1].date.day);
}
halt = end_id-1;
}
if(edt[i].group == grp) {
temp[len_temp] = edt[i];
len_temp++;
}
}
halt = 0;
len_temp = 0;
// F - Same over 2 weeks (-10)
// 2-week check
remaining = 2;
for(int i = end_id-1; i >= 0+halt; i--) {
if(i == 0 || (date_dist(edt[0].date, edt[i].date)%7 == 4 && date_dist(edt[0].date, edt[i+1].date)%7 != 4)) {
remaining -= 1;
if(remaining == 0 || i == 0) {
int dist = 0;
for(int j = 0; j < len_temp; j++) {
for(int k = j+1; k < len_temp; k++) {
dist = date_dist(temp[k].date, temp[j].date);
if(dist == 7 && temp[k].date.hour == temp[j].date.hour) {
score -= 20;
}
}
}
halt = end_id-1;
}
}
if(edt[i].group == grp) {
temp[len_temp] = edt[i];
len_temp++;
}
}
halt = 0;
len_temp = 0;
free(temp);
return score;
}
// typedef struct colleur {char* name; int namelen; topic mat; date* disp; int n_disp;} colleur;
colleur* get_colleurs(colleur* cl, int len_cl, date d, int* how_many) {
colleur* res = malloc(sizeof(colleur)*30); // max. 3 colles per creneau
//printf("X\n");
int ptr = 0;
//printf("[]\n");
for(int i = 0; i < len_cl; i++) {
for(int j = 0; j < cl[i].n_disp; j++) {
if(is_equal_date(cl[i].disp[j], d)) {
//printf("%s\n", cl[i].name);
if(ptr >= 30) {
printf("warning : too many colleurs detected for a creneau\n");
*how_many = 0;
return res;
}
res[ptr] = cl[i];
ptr++;
j = cl[i].n_disp;
}
}
}
*how_many = ptr;
return res;
}
void swap(int* arr, int i, int j) {
if(i != j) {
arr[i] += arr[j];
arr[j] = arr[i] - arr[j];
arr[i] -= arr[j];
}
}
void generate_random_perm(int* arr, int len) {
// generate a random perm of int between 0 and len-1
for(int i = 0; i < len; i++) {
arr[i] = i;
}
for(int i = 0; i < len; i++) {
swap(arr, i, rand()%len);
}
}
void print_arr(int* arr, int len) {
printf("[");
for(int i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("]\n");
}
/*
void shiftright_ncolles(int n_grps) {
for(int i = 0; i < n_grps; i++) {
n_colles[i] = (n_colles[i]+1)%4;
}
}
void shiftleft_ncolles(int n_grps) {
for(int i = 0; i < n_grps; i++) {
if(n_colles[i] == 0) {
n_colles[i] = 3;
} else {
n_colles[i]--;
}
}
}
void aux(int* abort, int* weeks_len, creneau* edt, int len_edt, colleur* chads, int n_chads, int n_groups, int n_weeks, int current_grp, int current_week, int current_offset, int starting_group, bool is_first) {
// append colles for specified week and group
//usleep(100000);
print_arr(stats, 10);
if(current_week > n_weeks) {
printf("Done\n");
*abort = true;
} else {
int n_available_i = 0;
int n_available_j = 0;
colleur* available_i = malloc(sizeof(colleur));
colleur* available_j = malloc(sizeof(colleur));
int picked_i = 0;
int picked_j = 0;
bool pass_i;
bool pass_j;
bool is_valid_i = false;
bool is_valid_j = false;
int* perms_i = malloc(sizeof(int)*30);
int* perms_j = malloc(sizeof(int)*30);
int succ = current_grp+1;
if(succ == n_groups+1) {
succ = 1;
}
printf("Colles for week %d, group %d {%d}\n", current_week, current_grp, (1-(*abort))*weeks_len[current_week-1]);
//for(int i = 0; i < weeks_len[current_week]; i++) { // loop for 1st colle
for(int i = 0; i < (1-(*abort))*weeks_len[current_week-1]; i++) { // loop for 1st colle
//printf("+1\n");
//printf("i(%d -> %d)i\n", current_grp, current_offset+i);
//printf(" ");
//printf("[%d]\n", current_offset+i);
//printf("I\n");
if(edt[current_offset+i].group == 0) {
free(available_i);
//get_colleurs(colleur* cl, int len_cl, date d, int* how_many) {
available_i = get_colleurs(chads, n_chads, edt[current_offset+i].date, &n_available_i);
if(n_available_i != 0) {
generate_random_perm(perms_i, n_available_i);
for(int ii = 0; ii < n_available_i; ii++) {
picked_i = perms_i[ii];
if(n_colles[current_grp-1] == 3) {
pass_i = available_i[picked_i].mat == PHYSICS || available_i[picked_i].mat == ENGLISH;
} else {
pass_i = available_i[picked_i].mat == MATH;
}
if(pass_i) {
// choose someone available
//picked_i = rand()%n_available_i;
// add the 1st colle
edt[current_offset+i].group = current_grp;
str_copy(available_i[picked_i].name, available_i[picked_i].namelen, edt[current_offset+i].name);
edt[current_offset+i].mat = available_i[picked_i].mat;
is_valid_i = is_allowed_MP2I(edt, len_edt, current_grp, edt[current_offset+i].date, 'i');
if(is_valid_i && *abort == 0) {
// /!\ DONT FORGET THE RECURSIVE CALL HERE (in case a group has only 1 colle that week)
//aux(weeks_len, edt, chads, n_chads, n_groups, n_weeks, current_grp, current_week, current_offset, starting_group, is_first);
if(succ == starting_group) {
//printf("---------------------------------------------------------\n");
shiftright_ncolles(n_groups);
aux(abort, weeks_len, edt, len_edt, chads, n_chads, n_groups, n_weeks, current_grp, current_week+1, current_offset+weeks_len[current_week-1], current_grp, true);
shiftleft_ncolles(n_groups);
} else {
if(current_grp == n_groups) {
aux(abort, weeks_len, edt, len_edt, chads, n_chads, n_groups, n_weeks, 1, current_week, current_offset, starting_group, false);
} else {
aux(abort, weeks_len, edt, len_edt, chads, n_chads, n_groups, n_weeks, current_grp+1, current_week, current_offset, starting_group, is_first);
}
}
} else {
stats[8]++;
}
for(int j = 0; j < (1-(*abort))*weeks_len[current_week-1]*(n_colles[current_grp-1] != 3); j++) { // loop for 2nd colle
//printf("j(%d -> %d)j\n", current_grp, current_offset+j);
//printf(" ");
//printf("[%d]\n", current_offset+i);
//printf("I\n");
if(edt[current_offset+j].group == 0) {
free(available_j);
//get_colleurs(colleur* cl, int len_cl, date d, int* how_many) {
available_j = get_colleurs(chads, n_chads, edt[current_offset+j].date, &n_available_j);
if(n_available_j != 0) {
generate_random_perm(perms_j, n_available_j);
for(int jj = 0; jj < n_available_j; jj++) {
// choose someone available
//picked_j = rand()%n_available_j;
picked_j = perms_j[jj];
if(available_j[picked_j].mat != MATH) {
// add the 1st colle
edt[current_offset+j].group = current_grp;
str_copy(available_j[picked_j].name, available_j[picked_j].namelen, edt[current_offset+j].name);
edt[current_offset+j].mat = available_i[picked_j].mat;
is_valid_j = is_allowed_MP2I(edt, len_edt, current_grp, edt[current_offset+j].date, 'j');
if(is_valid_j && *abort == 0) {
// THE RECURSIVE CALL
//aux(weeks_len, edt, chads, n_chads, n_groups, n_weeks, current_grp, current_week, current_offset, starting_group, is_first);
if(succ == starting_group) {
//printf("---------------------------------------------------------\n");
shiftright_ncolles(n_groups);
aux(abort, weeks_len, edt, len_edt, chads, n_chads, n_groups, n_weeks, current_grp, current_week+1, current_offset+weeks_len[current_week-1], current_grp, true);
shiftleft_ncolles(n_groups);
} else {
if(current_grp == n_groups) {
aux(abort, weeks_len, edt, len_edt, chads, n_chads, n_groups, n_weeks, 1, current_week, current_offset, starting_group, false);
} else {
aux(abort, weeks_len, edt, len_edt, chads, n_chads, n_groups, n_weeks, current_grp+1, current_week, current_offset, starting_group, is_first);
}
}
} else {
stats[9]++;
}
if(*abort == 0) {
// remove 2nd colle in case it's blocked
edt[current_offset+j].group = 0;
edt[current_offset+j].name[0] = '\0';
edt[current_offset+j].mat = NOTHING;
}
}
}
} else {
//printf("Occupied 2nd colle\n");
}
}
}
if(*abort == 0) {
// remove 1st colle in case it's blocked
edt[current_offset+i].group = 0;
edt[current_offset+i].name[0] = '\0';
edt[current_offset+i].mat = NOTHING;
}
}
}
}
} else {
//printf("Occupied 1st colle\n");
}
}
free(available_i);
free(available_j);
free(perms_i);
free(perms_j);
}
//printf("[terminated : group %d with week %d]\n", current_grp, current_week);
}
void generate_colles_v1(creneau* edt, int len_edt, colleur* chads, int n_chads, int n_groups, int n_weeks) {
// Fill edt with a colloscope
// The final function
int* weeks_len = malloc(sizeof(int)*n_weeks);
int ptr = 0;
int current = 1;
for(int k = 1; k < len_edt; k++) {
if(date_dist(edt[k-1].date, edt[k].date) > 1 || k == len_edt-1) {
weeks_len[ptr] = current + (k == len_edt - 1);
current = 0;
ptr++;
}
current++;
}
print_arr(weeks_len, n_weeks);
stats = malloc(sizeof(int)*10);
for(int i = 0; i < 10; i++) {
stats[i] = 0;
}
n_colles = malloc(sizeof(int)*n_groups);
for(int i = 0; i < n_groups; i++) {
n_colles[i] = i%4;
}
// invariant : if n_colles[grp-1] = 3 then grp has only 1 colle that week
//print_arr(n_colles, n_groups);
//assert(0);
printf("Entering aux\n");
int abort = 0;
int* ptrbool = &abort;
aux(ptrbool, weeks_len, edt, len_edt, chads, n_chads, n_groups, n_weeks, 1, 1, 0, 1, true);
//aux(weeks_len, edt, len_edt, chads, n_chads, n_groups, n_weeks, 1, current_week, current_offset, starting_group, false);
system("clear");
print_one_week(edt, len_edt, edt[0].date);
printf("\n");
print_one_week(edt, len_edt, edt[16].date);
printf("\n");
print_one_week(edt, len_edt, edt[32].date);
printf("\n");
print_one_week(edt, len_edt, edt[48].date);
free(weeks_len);
free(stats);
free(n_colles);
printf("It's over\n");
}
*/
// ----------------------------------------------------- //
// ------------------| NEW ALGORITHM |------------------ //
// ----------------------------------------------------- //
void add_colle(creneau* edt, colleur* chads, int grp, int id_edt, int id_chad) {
edt[id_edt].group = grp;
edt[id_edt].namelen = chads[id_chad].namelen;
str_copy(chads[id_chad].name, chads[id_chad].namelen, edt[id_edt].name);
edt[id_edt].mat = chads[id_chad].mat;
//printf("{%d %s %d %d %d}\n", edt[id_edt].group, edt[id_edt].name, edt[id_edt].namelen, (int)(edt[id_edt].mat), id_edt);
}
void remove_colle(creneau* edt, int id_edt) {
edt[id_edt].group = 0;
str_copy("none", 4, edt[id_edt].name);
edt[id_edt].namelen = 0;
edt[id_edt].mat = NOTHING;
}
bool is_overlap(creneau* edt, int len_edt, int id) { // detect if a colleur has 2 colles at the same time
int k = 1;
while(id+k < len_edt && is_equal_date(edt[id].date, edt[id+k].date)) {
if(str_equal(edt[id].name, edt[id+k].name)) {
return true;
}
k++;
}
k = 1;
while(id-k >= 0 && is_equal_date(edt[id].date, edt[id-k].date)) {
if(str_equal(edt[id].name, edt[id-k].name)) {
return true;
}
k++;
}
return false;
}
bool is_overlap_creneau(creneau* edt, int len_edt, int id, int grp) { // detect if a group has 2 overlapping colles
int k = 1;
while((id+k < len_edt && edt[id+k].date.hour - edt[id].date.hour < edt[id].length) && edt[id+k].date.day == edt[id].date.day) {
if(edt[id+k].group == grp) {
return true;
}
k++;
}
return false;
}
void add_colles_for_group_MP2I(int* weeks_len, creneau* edt, int len_edt, colleur* chads, int len_chads, int n_weeks, int grp, topic start_rotation, int mth, int inf, int* skip_count) {
topic rotation = start_rotation; // physics/english rotation
int math = mth; // math (3/4)
int info = inf; // info (1/6)
int r; // randomize the 1st date
int k = 0; // offset
int halt = 0; // timeout in case a colle cannot be placed
bool found; // interrupt in case a valid colle has been found
int remaining_to_add = 0; /* self-explainatory
please note that this also tells what colle to add :
1 = physics/english colle
2 = math
3 (not implemented) = info
*/
colleur* dudes = malloc(sizeof(colleur)*2); // used to import colleurs available for a creneau
int len_dudes = 0; // length of colleur*
int* perm = malloc(sizeof(int)*30); // randomize who to pick
int len_perm = 0; // length of int*
bool has_math_dude = false; // length of colleur*
//printf("\n");
for(int week = 0; week < n_weeks; week++) {
int weeklen = weeks_len[week];
// update what colles to add
if(math == 0) {
math = 3;
} else {
remaining_to_add++;
math--;
}
if(rotation == ENGLISH) {
rotation = PHYSICS;
} else {
rotation = ENGLISH;
}
remaining_to_add++; // physics/english
//printf("%d -> (%d %d)\n", grp, week, remaining_to_add);
// initialize/reset variables
r = rand()%weeklen;
halt = 0;
found = false;
info++;
// info colle
while(info >= 6) {
if(edt[k+r%weeklen].group == 0 && edt[k+r%weeklen].length == 2) {
// if creneau is empty
// import all colleurs available
free(dudes);
dudes = get_colleurs(chads, len_chads, edt[k+r%weeklen].date, &len_dudes);
len_perm = len_dudes;
// if there are colleurs available
if(len_dudes != 0) {
// randomize the order of colleurs
generate_random_perm(perm, len_perm);
// for each one of them, add his colle for selected group pf and only if
// - he is a INFO colleur
// if a colle has been addded, interrupt the for and while loops
for(int dude = 0; dude < len_perm*(1-found); dude++) {
if(dudes[perm[dude]].mat == INFO && !is_overlap_creneau(edt, len_edt, k+r%weeklen, grp)) {
add_colle(edt, dudes, grp, k+r%weeklen, perm[dude]);
found = true;
info = 0;
}
}
}
}
if(!found && halt > weeklen) {
info = 0;
//printf("Warning : skipping info colle for week %d and group %d\n", week+1, grp);
*skip_count += 1;
}
r++;
halt++;
}
// reset the variables
r = rand()%weeklen;
found = false;
halt = 0;
// if there is a math colle to add, enter this loop
while(remaining_to_add == 2) {
if(edt[k+r%weeklen].mat == NOTHING && edt[k+r%weeklen].length == 1) {
// if creneau is empty
// import all colleurs available
free(dudes);
dudes = get_colleurs(chads, len_chads, edt[k+r%weeklen].date, &len_dudes);
len_perm = len_dudes;
// if there are colleurs available
if(len_dudes != 0) {
// randomize the order of colleurs
generate_random_perm(perm, len_perm);
// for each one of them, add his colle for selected group pf and only if
// - he is a MATH colleur
// - he does not have another colle at the same time (is_overlap)
// if a colle has been addded, interrupt the for andwhile loops
for(int dude = 0; dude < len_perm*(1-found); dude++) {
if(dudes[perm[dude]].mat == MATH) {
add_colle(edt, dudes, grp, k+r%weeklen, perm[dude]);
if(is_overlap(edt, len_edt, k+r%weeklen)) {
remove_colle(edt, k+r%weeklen);
} else {
found = true;
remaining_to_add--;
//printf("+math for week %d and group %d (index %d)\n", week, grp, k+r%weeklen);
}
}
}
}
}
if(!found && halt > weeklen) {
remaining_to_add--;
//printf("Warning : skipping math colle for week %d and group %d\n", week+1, grp);
*skip_count += 1;
}
r++;
halt++;
}
// reset the variables
r = rand()%weeklen;
found = false;
halt = 0;
// do it again for physics/english colles
while(remaining_to_add == 1) {
if(edt[k+r%weeklen].mat == NOTHING && edt[k+r%weeklen].length == 1) {
dudes = get_colleurs(chads, len_chads, edt[k+r%16].date, &len_dudes);
len_perm = len_dudes;
if(len_dudes != 0) {
generate_random_perm(perm, len_perm);
has_math_dude = false;
/*for(int dude = 0; dude < len_perm*(1-has_math_dude); dude++) {
if(dudes[dude].mat == MATH) {
has_math_dude = true;
}
}*/
for(int dude = 0; dude < len_perm*(1-found)*(1-has_math_dude); dude++) {
//printf("%d\n", chads[perm[dude]]);
if(dudes[perm[dude]].mat == rotation) {
add_colle(edt, dudes, grp, k+r%weeklen, perm[dude]);
found = true;
remaining_to_add--;
//printf("+secondary for week %d and group %d (index %d)\n", week, grp, k+r%weeklen);
}
}
}
}
if(!found && halt > weeks_len[week]) {
remaining_to_add--;
//printf("Warning : skipping secondary colle for week %d and group %d\n", week+1, grp);
*skip_count += 1;
}
r++;
halt++;
}
k += weeks_len[week];
remaining_to_add = 0;
}
// avoid memory loss
free(perm);
free(dudes);
}
void write_to_file(char* filename, creneau* edt, int len_edt) {
FILE* ptr = fopen(filename, "w");
fprintf(ptr, "hour,day,month,year,length,group,colleur,matiere\n");
for(int i = 0; i < len_edt; i++) {
fprintf(ptr, "%d,%d,%d,%d,%d,%d,%s,", edt[i].date.hour, edt[i].date.day, edt[i].date.month, edt[i].date.year, edt[i].length, edt[i].group, edt[i].name);
if(edt[i].mat == NOTHING) {
fprintf(ptr, "none");
} else if(edt[i].mat == MATH) {
fprintf(ptr, "Maths");
} else if(edt[i].mat == PHYSICS) {
fprintf(ptr, "Physique");
} else if(edt[i].mat == ENGLISH) {
fprintf(ptr, "Anglais");
} else if(edt[i].mat == INFO) {
fprintf(ptr, "Info");
} else if(edt[i].mat == FRENCH) {
fprintf(ptr, "Français");
} else {
fprintf(ptr, "Unknown");
}
fprintf(ptr, "\n");
}
fclose(ptr);
}
int min(int x, int y) {
if(x < y) {
return x;
}
return y;
}
int max(int x, int y) {
if(x > y) {
return x;
}
return y;
}
int score(creneau* edt, int len_edt, int grp) {
int score = 100;
int dist = 0;
for(int i = 0; i < len_edt; i++) {
for(int j = i+1; j < len_edt; j++) {
if(edt[i].group == grp && edt[j].group == grp) {
dist = date_dist(edt[i].date, edt[j].date);
if(dist == 0) {
score -= 7;
}
/*if(str_equal(edt[i].name, edt[j].name)) {
printf("%d\n", dist);
score -= max(0, 28-dist);
}*/
if(dist == 7 && edt[i].date.hour == edt[j].date.hour) {
score -= 5;
}
if(dist < 5 && edt[i].date.hour == 18 && edt[j].date.hour == 18) {
score -= 10;
}
}
}
}
return score;
}
void aux_2(creneau* edt, int len_edt, colleur* chads, int len_chads, int n_groups, int n_weeks, int n_sim) {
int start = time(NULL);
int* weeks_len = malloc(sizeof(int)*n_weeks);
// this list is used to tell the above code what index of edt it has to go to search for a colle
int ptr = 0;
int current = 1;
for(int k = 1; k < len_edt; k++) {
if(date_dist(edt[k-1].date, edt[k].date) > 1 || k == len_edt-1) {
weeks_len[ptr] = current + (k == len_edt - 1);
current = 0;
ptr++;
}
current++;
}
/*
print_one_week(edt, len_edt, edt[0].date);
printf("\n");
print_one_week(edt, len_edt, edt[19].date);
printf("\n");
print_one_week(edt, len_edt, edt[38].date);
printf("\n");
print_one_week(edt, len_edt, edt[57].date);
*/
printf("\n");
int max_score = 0;
int global_min = 0;
int global_skipped = 0;
int screwed_group = 0;
int local_score = 0;
int local_min = 0;
int local_group = 0;
int temp = 0;
int skipped = 0;
int a = n_sim/100;
for(int k = 0; k < n_sim*(1 - (max_score == n_groups*100)); k++) {
if(k >= a) {
printf("\x1b[1F");
printf("\x1b[2K");
printf("%d Completed (current max is %d/%d)\n", 100*a/n_sim, max_score, 100*n_groups);
a += n_sim/100;
}
local_score = 0;
local_min = 100;
skipped = 0;
for(int i = 0; i < n_groups; i++) {
//for(int i = 0; i < 1; i++) {
//rintf("Adding colles for group %d...\n", i+1);
add_colles_for_group_MP2I(weeks_len, edt, len_edt, chads, len_chads, n_weeks, i+1, (topic)(2+i%2), i%4, i%6, &skipped);
}
for(int i = 0; i < n_groups; i++) {
//printf("Score for group %d : %d\n", i+1, score(edt, len_edt, i+1));
temp = score(edt, len_edt, i+1);
local_score += temp;
if(local_min > temp) {
local_min = temp;
local_group = i+1;
}
}
local_score -= skipped*30;
if(local_score > max_score) {
max_score = local_score;
screwed_group = local_group;
global_min = local_min;
global_skipped = skipped;
write_to_file("output.csv", edt, len_edt);
}
for(int r = 0; r < len_edt; r++) {
remove_colle(edt, r);
}
}
printf("\x1b[1F");
printf("\x1b[2K");
if(max_score == 100*n_groups) {
printf("Interrupting early due to a perfect score achieved\n");
} else {
printf("100 Completed, best score is %d/%d with %d skipped colle(s)\n", max_score, 100*n_groups, global_skipped);
printf("Most screwed group is %d with a score of %d/100\n", screwed_group, global_min);
}
int end = time(NULL);
printf("Took %ds to found\n", end-start);
}