#include #include #include #include "algorithm.h" 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; 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"); } 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; } int free_math_space(creneau* edt, int len_edt, int id) { int k = 1; int howmany = 0; while(id+k < len_edt && is_equal_date(edt[id].date, edt[id+k].date)) { if(edt[id+k].mat == NOTHING || edt[id+k].mat == MATH) { howmany++; } k++; } k = 1; while(id-k >= 0 && is_equal_date(edt[id].date, edt[id-k].date)) { if(edt[id-k].mat == NOTHING || edt[id-k].mat == MATH) { howmany++; } k++; } return howmany; } 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 */ int len_dudes = 0; // length of colleur* int len_perm = 0; // length of int* int math_dude = 0; // length of colleur* int weeklen; //printf("\n"); for(int week = 0; week < n_weeks; week++) { 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 colleur* 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 int* perm = malloc(sizeof(int)*len_perm); 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; } } free(perm); } free(dudes); } 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 colleur* 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 int* perm = malloc(sizeof(int)*len_perm); 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); } } } free(perm); } free(dudes); } 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) { colleur* dudes = get_colleurs(chads, len_chads, edt[k+r%weeklen].date, &len_dudes); len_perm = len_dudes; if(len_dudes != 0) { int* perm = malloc(sizeof(int)*len_perm); generate_random_perm(perm, len_perm); math_dude = 0; for(int dude = 0; dude < len_dudes; dude++) { if(dudes[dude].mat == MATH) { math_dude++; } } for(int dude = 0; dude < len_perm*(1-found); dude++) { //printf("%d\n", chads[perm[dude]]); if(dudes[perm[dude]].mat == rotation) { add_colle(edt, dudes, grp, k+r%weeklen, perm[dude]); if(math_dude > free_math_space(edt, len_edt, k+r%weeklen) || is_overlap(edt, len_edt, k+r%weeklen)) { remove_colle(edt, k+r%weeklen); } else { found = true; remaining_to_add--; ///rintf("+secondary for week %d and group %d (index %d)\n", week, grp, k+r%weeklen); } } } free(perm); } free(dudes); } 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; } } 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, "_"); } 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 -= 4; } /*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, char* outname) { 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++; } int* group_stats = malloc(sizeof(int)*n_groups); int* group_temp = malloc(sizeof(int)*n_groups); /* 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); */ int max_score = -900000; 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 = 0; printf("Testing %d combinations...\n", n_sim); printf("\n"); 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); add_colles_for_group_MP2I(weeks_len, edt, len_edt, chads, len_chads, n_weeks, i+1, (topic)(2+i%2), i%4, -20, &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; group_temp[i] = 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; for(int p = 0; p < n_groups; p++) { group_stats[p] = group_temp[p]; } write_to_file(outname, 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 (without skip penalty) with %d skipped colle(s)\n", max_score+global_skipped*30, 100*n_groups, global_skipped); printf("Most screwed group is %d with a score of %d/100\n", screwed_group, global_min); printf("Stats for all groups are :\n"); for(int i = 0; i < n_groups; i++) { printf("Group %d : %d/100\n", i+1, group_stats[i]); } } int end = time(NULL); printf("Took %ds to found\n", end-start); free(group_stats); free(group_temp); free(weeks_len); }