[1] Problema orarului școlar echilibrat și limbajul R
[2] V. Bazon - Orare școlare echilibrate și limbajul R https://books.google.ro/books?id=aWrDEAAAQBAJ
Întâi, echilibrăm distribuțiile claselor care în setul R12
rezultat mai sus, au ajuns să aibă peste 7 ore în vreo zi; apoi, trecem pe rând la cele pentru care diferența între cel mai mare și cel mai mic număr de ore pe zi a rămas mai mare ca 2, respectiv este egală cu 2 (caz în care îi mai zicem „cvasi-omogenă”; ideal ar fi să fie cel mult 1 – adică distribuția respectivă să fie omogenă, sau uniformă).
Ocupându-ne astfel de clase, urmărim mereu să menținem echilibrarea pe zile a distribuției globale (a tuturor lecțiilor din R12
) și deasemenea, urmărim să echilibrăm măcar unele distribuții individuale pentru profesori ai claselor respective.
În final, vedem care profesori au rămas cu distribuții neechilibrate și dacă este cazul, le echilibrăm (fără a dezechilibra altele) prin schimbarea uneia dintre lecții (evitând pe cele din P23
, pe clase cuplate), din ziua în care sunt multe ore, într-o zi în care sunt mai puține ore.
Probabil că vom realiza planul schițat mai sus în mai multe sesiuni de lucru cu R; ne vom baza de fiecare dată, pe un program "brush.R
" prin care – pe lângă pachetul tidyverse
– încărcăm setul (curent) R12i.RDS
și funcția anterioară change_zl()
(plus pentru orice eventualitate, R1.RDS
, R2.RDS
, Tw12.Rda
, vectorul Zile
și funcția decompose23()
).
În brush.R
vom copia când va fi cazul (redând și aici, când avem ceva modificări) unele funcții din [2] care servesc vizualizării corelate a lecțiilor și modificării interactive a setului R12
.
Având în vedere cum am obținut în R12
repartiția pe zile a lecțiilor (folosind funcțiile mount_days()
din [2]), avem puține clase cu mai mult de 7 ore într-o zi:
> cz <- table(R12[c('cls','zl')]) %>% apply(., 1, function(row) ifelse(any(row > 7), row, 0)) > names(cz[cz > 0]) %>% print() [1] "11B"
Pentru o clasă dată putem vizualiza distribuția, pe zile și pe categorii de lecții, prin funcția următoare (față de [2], avem acum și „categoria” dP23
– prin decompose23()
, din cls23_days.RDS
; în plus, am atribuit nume de linie, prin list2DF() %>% `rownames<-`
):
cls_hours <- function(cls_name) map(list(R1, R2, dP23), function(RC) RC %>% filter(cls == cls_name) %>% count(zl, .drop=FALSE) %>% pull(n) ) %>% setNames(c("R1", "R2", "dP23")) %>% list2DF() %>% `rownames<-`(Zile) > t(cls_hours("11B")) %>% print() # t() transpune liniile pe coloane Lu Ma Mi Jo Vi R1 4 4 5 5 5 R2 1 0 0 1 2 dP23 1 0 0 0 1
Așadar, 11B
are 8 ore Vi
și 4 ore Ma
(și este singura clasă cu mai mult de 7 ore într-o zi); care lecție s-o mutăm din ziua Vi
, în ziua Ma
? În principiu, nu una care există deja în ziua Ma
– caz în care profesorul respectiv ar căpăta Ma
două ore la o aceeași clasă; nu acceptăm fără motiv serios (principial), ca un profesor să aibă două sau mai multe lecții „identice” într-o aceeași zi, la o aceeași clasă (în particular… dacă are pe o disciplină exact 3 ore în școală, dar la o aceeași clasă – atunci va trebui să vină în trei zile și nu într-una singură).
mount_days()
nu repartizează două lecții prof|cls
identice într-o aceeași zi, decât dacă disciplina implicată are mai mult de 5 ore pe săptămână; singurii cărora li s-a repartizat aceeași clasă de două ori într-o zi, ar fi eventual unii profesori implicați în cuplaje (din R2
, sau din P23
), în situația când au multe lecții, incluzând și lecții proprii (în R1
).
Următoarea funcție preia – cu o mică îmbunătățire și sub un nume parcă mai potrivit – funcția "prof_in_one_day
" din [2], furnizând distribuția lecțiilor acelor profesori care la o clasă dată, au lecții într-o zi dar nu și în cealaltă:
diff_prof <- function(cls_name, z1, z2, RC) { # RC = R1 | R2 | R12 Q <- RC %>% filter(cls == cls_name & zl %in% c(z1, z2)) %>% split(.$zl) P1 <- Q[[z1]]$prof P2 <- Q[[z2]]$prof Pr <- setdiff(P1, P2) # o mică simplificare, față de [2] NH <- table(RC[c('prof', 'zl')])[Pr, ] if(length(Pr) == 1) { # când table() ar returna un 'array' 1-dimensional dim(NH) <- c(1, 5) dimnames(NH) <- list(Pr, Zile) } NH } # cei cu ore (în RC) la clasa cls_name în ziua z1, dar NU și în z2
Dar subliniem acest aspect: în RC
, câmpul prof
trebuie să fie de tip character și nu factor; altfel – fiindcă table()
ar angaja indecșii numerici din levels()
– în NH
ar rezulta alte nume decât cele corecte (noi am avut grijă din timp, ca R2$prof
și R12$prof
să fie character).
Acum putem folosi funcția recast12()
din [2] (copiind-o în brush.R
și schimbând numele de funcție menționat mai sus); redăm de pe ecran interacțiunea respectivă:
> recast12("11B") 11B 6 4 5 6 8 index Z1 și index Z2: 5 2 Vi --> Ma zl prof Lu Ma Mi Jo Vi # au ore Vi, dar nu și Ma LR1 4 4 5 4 3 Rl2 2 2 4 4 3 Is2 3 4 4 2 3 LI3 3 1 2 2 2 LG1 4 3 6 4 4 index-prof, de mutat (0 = Cancel): 2 6 5 5 6 7 # noua distribuție pentru 11B (încă neuniformă) > recast12("11B") 11B 6 5 5 6 7 index Z1 și index Z2: 5 2 Vi --> Ma zl prof Lu Ma Mi Jo Vi # rămași cu ore Vi, dar nu și Ma LR1 4 4 5 4 3 Is2 3 4 4 2 3 LI3 3 1 2 2 2 LG1 4 3 6 4 4 index-prof, de mutat (0 = Cancel): 3 6 6 5 6 6 # 11B are acum o distribuție omogenă > addmargins(table(R12$zl)) # efectul asupra distribuției globale Lu Ma Mi Jo Vi Sum 185 187 187 184 185 928
Cele două schimbări de lecții echilibrează distribuția la 11B
, dar nu afectează caracterul de "cvasi-omogen" al distribuțiilor individuale pentru profesorii implicați (Rl2
și LI3
) și nu afectează prea mult, distribuția pe zile din R12
.
După asemenea secvențe de modificări, se cuvine să salvăm în R12i.RDS
noua distribuție R12
– încât într-o sesiune de lucru ulterioară, brush.R
să încarce ”ultimul” set R12
; dar dacă vrem totuși să abandonăm toate modificările făcute între timp și „s-o luăm de la capăt” – atunci putem reinițializa R12i.RDS
din seturile R1.RDS
, R2.RDS
și P23
(acestea, pe tot parcursul, nu sunt afectate de modificări).
În setul curent R12
, au rămas clase la care diferența de ore pe zi este mai mare ca 2:
dh <- table(R12[c('cls','zl')]) %>% apply(., 1, function(row) ifelse(diff(range(row)) > 2, row, 0)) > names(dh[dh > 0]) %>% print [1] "10A" "12B"
Să echilibrăm distribuția lecțiilor la clasa 10A
:
> recast12("10A") 10A 7 4 6 7 7 index Z1 și index Z2: 1 2 # o primă încercare... Lu --> Ma zl prof Lu Ma Mi Jo Vi # au ore (la 10A) Lu, dar nu și Ma LE3 4 4 4 4 3 Fz1 6 5 5 5 7 LI2LI1 1 0 1 1 0 LG2 4 5 4 6 4 index-prof, de mutat (0 = Cancel): 0 # abandonează
Nu ne-a convenit să schimbăm din Lu
în Ma
: fie am „strica” echilibrul (la LE3
, sau la LG2
), fie ar fi nepotrivit în acest moment (la Fz1
, la care potrivit ar fi să alegem pentru schimbare lecția de Vi
, când are 7 ore), fie ar trebui să verificăm și distribuția altui profesor (în cazul cuplajului LI2LI1
, ca și în cazul lui LG2
care are și lecții în P23
).
Dacă am schimba de Jo
pe Ma
, atunci Jo
ar rămâne în total 183 de ore; preferăm să schimbăm de Vi
(rămânând cu 184 de ore) pe Ma
, cu echilibrarea distribuției la Fz1
:
> recast12("10A") 10A 7 4 6 7 7 index Z1 și index Z2: 5 2 Vi --> Ma zl prof Lu Ma Mi Jo Vi LE3 4 4 4 4 3 Fz1 6 5 5 5 7 Bl1 3 4 4 3 5 Ps1 3 2 1 1 2 Tc2 2 3 2 3 3 LG2 4 5 4 6 4 index-prof, de mutat (0 = Cancel): 2 7 5 6 7 6 # încă neechilibrat
Până la urmă, pentru a echilibra… trebuie să facem și o schimbare dintre cele două pe care le-am evitat mai sus (fie de Lu
fie de Jo
, pe Ma
):
> recast12("10A") 10A 7 5 6 7 6 index Z1 și index Z2: 4 2 Jo --> Ma zl prof Lu Ma Mi Jo Vi Ch1 4 2 4 4 4 Is3 4 3 3 3 3 Bl1 3 4 4 3 5 Rl2 2 3 4 4 2 LI2LI1 1 0 1 1 0 Ds1 4 4 4 4 3 index-prof, de mutat (0 = Cancel): 1 7 6 6 6 6
Deocamdată, distribuția globală s-a deteriorat (185 189 187 183 184
); dar măcar, am echilibrat și distribuția lui Ch1
(pe lângă cea a clasei 10A
).
Procedăm la fel, pentru 12B
:
> recast12("12B") 12B 5 7 7 5 4 index Z1 și index Z2: 2 5 Ma --> Vi zl prof Lu Ma Mi Jo Vi Fz3 2 3 3 3 2 Fl1 4 4 4 3 3 Tc2 2 3 2 3 3 LG1 4 3 6 4 4 index-prof, de mutat (0 = Cancel): 2 5 6 7 5 5 # încă neechilibrat > recast12("12B") 12B 5 6 7 5 5 index Z1 și index Z2: 3 4 Mi --> Jo zl prof Lu Ma Mi Jo Vi Fz3 2 3 3 3 2 LR1 4 4 5 4 3 Bl1 3 4 4 3 5 Mt3 4 5 5 3 4 Ch1 4 3 4 3 4 LG1 4 3 6 4 4 index-prof, de mutat (0 = Cancel): 4 5 6 6 6 5 > table(R12$zl) Lu Ma Mi Jo Vi 185 188 186 184 185 > saveRDS(R12, "R12i.RDS")
Echilibrând astfel distribuția la 12B
, cea pentru Fl1
rămâne omogenă, iar cea a lui Mt3
devine una omogenă; distribuția globală încă rămâne, ușor „defectuoasă”.
Refăcând calculul de mai sus al diferenței dh
, dar acum în condiția diff(range(row)) == 2
, vedem că există 17 clase la care într-o zi sunt cu două ore mai mult ca în alte zile:
> ndh <- names(dh[dh > 0]) > table(R12[c('cls', 'zl')])[ndh, ] zl cls Lu Ma Mi Jo Vi 10B 7 5 5 5 7 # a muta de Lu și de Vi, în alte două zile 10D 5 6 7 6 5 # a muta de Mi, pe Lu sau Vi 10E 5 5 6 6 7 10F 5 5 6 6 7 11A 7 6 6 6 5 # Lu --> Vi 11D 7 5 6 5 6 11E 6 5 5 6 7 11F 6 5 5 6 7 12A 6 7 6 5 5 # Ma (188) --> Jo (184) 12D 5 7 6 5 5 6A 6 5 7 5 5 9A 6 7 6 5 7 9B 6 7 6 5 5 9C 5 7 7 5 5 9D 5 7 5 7 5 9E 5 6 7 6 5 9F 5 6 6 7 5
Numai la 11A
, cele două zile între care ar trebui să schimbăm o lecție pentru a echilibra distribuția existentă, sunt „obligatorii” (din Lu
în Vi
):
> recast12("11A") 11A 7 6 6 6 5 index Z1 și index Z2: 1 5 Lu --> Vi zl prof Lu Ma Mi Jo Vi Gg1 3 4 3 5 5 Ch1 4 3 4 3 4 Rl2 2 3 4 4 2 LI3 3 2 2 2 1 index-prof, de mutat (0 = Cancel): 4 6 6 6 6 6
Aparent, am echilibrat și distribuția lui LI3
; de fapt, ar trebui să verificăm, fiindcă LI3
are la 11A
și ore în cuplajul LI1LI3
:
> R12 %>% filter(grepl("LI3", prof)) %>% arrange(zl, cls) prof cls zl 1 LI3 11B Lu 2 LI3 11D Lu # Lu: 2 ore 3 LI1LI3 11A Ma 4 LI3 11A Ma 5 LI3 11B Ma 6 LI2LI3 9A Ma # Ma: 4 ore 7 LI1LI3 11A Mi 8 LI3 11A Mi 9 LI3 11D Mi # Mi: 3 ore 10 LI1LI3 11A Jo 11 LI3 11A Jo 12 LI3 11B Jo 13 LI2LI3 9A Jo # Jo: 4 ore 14 LI3 11A Vi 15 LI3 11B Vi 16 LI2LI3 9A Vi # Vi: 3 ore
Deci distribuția orelor lui LI3
rămâne deocamdată cvasi-omogenă (cum era și înainte de a-i muta 11A
din ziua 1 în a 5-a).
Încercăm acum să trecem 12A
de la Ma
la Jo
, pentru a reduce totalul de ore pe ziua Ma
:
> recast12("12A") 12A 6 7 6 5 5 index Z1 și index Z2: 2 4 Ma --> Jo zl prof Lu Ma Mi Jo Vi Is3 4 3 3 3 3 Mt2 5 5 3 3 5 LI1 2 3 2 1 2 LG3 4 5 3 3 4 index-prof, de mutat (0 = Cancel): 2 6 6 6 6 5 > table(R12$zl) Lu Ma Mi Jo Vi 184 187 186 185 186 > saveRDS(R12, "R12i.RDS")
Distribuția globală s-a apropiat de „uniform” (ar mai fi de mutat o oră Ma
--> Lu
, pentru uniformizare); iar Mt2
a căpătat o distribuție mai omogenă ca înainte, pentru orelor sale.
O mutare Ma
--> Lu
s-ar putea face la clasa 12D
(există și riscul de a regreta mai târziu…):
> recast12("12D") 12D 5 7 6 5 5 index Z1 și index Z2: 2 1 Ma --> Lu zl prof Lu Ma Mi Jo Vi Tc1 4 5 4 5 3 Mt4 4 4 3 3 4 LE1 4 4 4 4 2 Sp1 4 4 4 5 4 LG4 4 4 5 4 4 index-prof, de mutat (0 = Cancel): 1 6 6 6 5 5
Distribuția s-a omogenizat la 12D
, a rămas cvasi-omogenă la Tc1
și a devenit omogenă (185 186 186 185 186
) pe totalul orelor.
Ne-au rămas 14 clase, la care avem de uniformizat distribuțiile:
> table(R12[c('cls', 'zl')])[setdiff(ndh, c("11A", "12A", "12D")), ] cls Lu Ma Mi Jo Vi 10B 7 5 5 5 7 10D 5 6 7 6 5 10E 5 5 6 6 7 10F 5 5 6 6 7 11D 7 5 6 5 6 11E 6 5 5 6 7 11F 6 5 5 6 7 6A 6 5 7 5 5 9A 6 7 6 5 7 9B 6 7 6 5 5 9C 5 7 7 5 5 9D 5 7 5 7 5 9E 5 6 7 6 5 9F 5 6 6 7 5
Folosim ca și în exemplificările de mai sus recast12()
, căutând mereu să nu „stricăm”, decât eventual temporar, echilibrele deja obținute (și desigur, să echilibrăm încă unele distribuții individuale). Pare să fie ceva caznă, dar lucrurile decurg din aproape în aproape, „identic” celor desfășurate mai sus (și ne-am abține să le mai detaliem aici).
Dar acest "din aproape în aproape" poate fi cumva, plănuit (cu iz de „inteligență”), ghidându-ne întâi după dispoziția lui '7
' pe coloane; pentru Lu
--> Ma
, candidații sunt 10B
și 11D
(singurele rămase cu 7 ore în ziua Lu
și în mod fericit, cu 5 ore Ma
); pentru a păstra omogenitatea distribuției globale, trebuie să transferăm invers, Ma
--> Lu
, două clase – și avem candidați (situația fericită), 9C
și 9D
(singurele de fapt, cu 7 ore Ma
și 5 ore Lu
).
Dacă aceste transferuri Lu
<--> Ma
reușesc în mod „onorabil”, atunci actualizăm pe ecran tabelul de mai sus și repetăm procedura de transfer între câte două zile (pe câte două clase); iar dacă vedem din datele afișate de recast12()
, că transferurile plănuite ar strica „neonorabil” echilibrele existente, atunci le abandonăm și încercăm transferuri pe o altă pereche de coloane, din tabelul curent (și după caz, mai folosim și transferuri bilaterale intermediare, între "7" și "6", sau între "6" și "5").
Folosind acest plan de lucru (dar relaxat, investigând mereu lucrurile și… gândindu-ne în van cum le-am putea „automatiza”), nouă ne-a luat cam 3 ore (probabil, de două-trei ori mai mult decât era necesar) pentru a ajunge la o repartiție R12i.RDS
care este omogenă (185 186 185 186 186
) și în care fiecare clasă are o distribuție omogenă a lecțiilor sale, pe zilele săptămânii; iar distribuțiile individuale (pentru profesori) sunt în bună parte, omogene (celelalte sunt cvasi-omogene, cum le-a lăsat mount_days()
).
Obs. Am repetat de nenumărate ori (prin "Copy&Paste") calculul dh
de mai sus, prin care obțineam clasele pentru care în setul R12
curent, diferența dintre cel mai mare și cel mai mic număr de ore pe zi este 2 – iar apoi, selectam distribuțiile corespunzătoare acestora prin table(R12[c('cls', 'zl')])[names(dh[dh > 0]), ]
…
Se cuvenea desigur, să fi încorporat în brush.R
o funcție care să producă direct datele respective (fără să fie necesar și un al doilea apel table()
):
cls_diff_hours <- function(d) table(R12[c('cls','zl')]) %>% apply(., 1, function(row) if(diff(range(row)) == d) row) %>% compact() %>% list2DF() %>% as.matrix() %>% t() %>% `colnames<-`(Zile)
De exemplu, constatăm (cu d=0
) că în acest moment, în R12
avem o singură clasă care are în fiecare zi un același număr de ore:
> cls_diff_hours(0) Lu Ma Mi Jo Vi 11A 6 6 6 6 6
Și anume, 11A
are câte 6 ore/zi; celelalte clase au fie 6 sau 7 ore/zi, fie 5 sau 6 ore/zi (matricea distribuțiilor rezultând prin cls_diff_hours(d=1)
).
Obs. Pentru un profesor care are și lecții cuplate, se poate ca distribuția cumulată (incluzând și orele cuplajelor în care este angajat) să aibă o zi cu 7 ore – dar în distribuția curentă R12
, clasele implicate să nu aibă, niciuna, 7 ore în ziua respectivă (avem în [2], un astfel de caz). Însă a fost ușor de verificat că în R12i.RDS
, nu întâlnim această situație.
Următoarea funcție (adaptată din [2]) produce un „tabel” pentru distribuțiile individuale neomogene existente în setul R12
curent, ale profesorilor neimplicați în cuplaje și care au măcar 9 ore pe săptămână:
twins <- names(Tw1) %>% union(names(Tw2)) %>% union(unique(dP23$prof)) # exterior funcției, evitând recalcularea vct_neunif <- function() { tpz <- table(R12[c('prof', 'zl')]) # pe setul curent R12 NU <- apply(tpz, 1, function(H) if(diff(range(H)) >= 2 & sum(H) > 8) H) %>% compact() %>% list2DF() Prof <- setdiff(names(NU), twins) # restrânge la R1 NU %>% select(all_of(Prof)) } # neangajați în cuplaje, cu distribuții curente neomogene, cu măcar 9 ore
Astfel, în R12i.RDS
avem în acest moment, 14 distribuții individuale cvasi-omogene (pe totaluri de câte măcar 9 ore):
> vct_neunif() Bl2 CC1 ET1 Gg1 Gg2 Is1 Is2 LE2 LR1 LR2 Mt2 Mt5 Ps1 Rl2 1 4 5 1 4 4 5 4 3 4 5 5 3 3 2 2 4 3 2 4 5 4 4 4 4 3 4 4 2 3 3 5 5 1 3 3 3 3 3 5 4 3 2 1 3 4 4 4 3 4 4 3 2 3 4 3 4 3 1 4 5 3 3 3 5 4 5 3 5 3 4 5 4 2 3
Ne străduim acum să le omogenizăm și pe acestea, pe cât vom putea.
Mai întâi, asociem unui profesor o matrice cu linii pentru fiecare zi, având o singură coloană pe care înregistrăm (separând cu spațiu) clasele repartizate zilnic acestuia:
framedist <- function(P) { ds <- R12 %>% filter(prof == P) %>% split(.$zl) for(z in Zile) ds[[z]] <- paste(ds[[z]]$cls, collapse=" ") frm <- ds[[1]] %>% setNames(P) for(j in 2:5) frm <- rbind(frm, ds[[j]]) attr(frm, "dimnames")[[1]] <- rep("", 5) frm }
De exemplu, să vedem pe ecran „cadrul” asociat distribuției curente a lui Bl2
:
> framedist("Bl2") Bl2 "10C 11B 7A 9C" "10C 7A 9C 9F" "5B 7A 7B 9B 9E" "5A 8A 9B 9C" "11E 7B 8B"
Funcția următoare mapează framedist()
pe vectorul returnat de vct_neunif()
(din care omite P
) și este o rescriere categoric simplificată, a funcției cu același nume din [2]:
swap_list <- function(P, z1, z2) { # z1 și z2 din Zile (nu indecși numerici) Prof <- names(vct_neunif()) D <- R12 %>% filter(prof %in% Prof) qPz1 <- D[D$prof==P & D$zl==z1, 2] # clasele lui P în z1 map(setdiff(Prof, P), function(P1) { ds2 <- D %>% filter(prof == P1) qP1z2 <- ds2[ds2$zl==z2, 2] # clasele lui P1 în z2 qP1z1 <- ds2[ds2$zl==z1, 2] # și clasele lui P1 în z1 if(length(qP1z2) <= length(qP1z1)) return(NULL) # P1 NU are mai puține clase în z2 ca în z1 c12 <- intersect(qPz1, qP1z2) if(length(c12) && length(intersect(c12, qP1z1)) < length(c12)) return(framedist(P1)) }) %>% compact() }
Văzând distribuția lui P
, ne dăm seama din care zi z1
să mutăm una dintre clasele respective în ziua z2
(în scopul uniformizării); apoi, swap_list()
ne dă profesorii P1
care: au mai multe ore în z2
, decât în z1
(invers față de P
); au în z2
clase dintre cele aflate la P
în z1
și măcar una dintre acestea, nu figurează la P1
și în ziua z1
.
Rezultă un mecanism de uniformizare pe care îl ilustrăm aici pentru Bl2
; acesta are distribuția (4 4 5 4 3)
), care ar deveni uniformă printr-un transfer Mi
--> Vi
; dar pentru a nu dezechilibra distribuția globală pe zile, trebuie căutat un alt profesor, căruia să-i transferăm invers clasa respectivă (Vi
--> Mi
):
> swap_list("Bl2", "Mi", "Vi") # Bl2 are Mi clasele 5B 7A 7B 9B 9E ET1 "8A" "6B 8B" "5B" "5A 6A 7A" "5A 5B 7B" Gg1 "11A 5A 5B 9D" "10A 9A 9B 9E" "10E 11B 11E" "10B 12A 12B 9C" "10E 11E 12D 7A 9E" LE2 "11A 12B 9B" "10B 10D 11E 12F" "11E 12F 9F" "10D 12F 9F" "10B 11A 12B 9B 9F"
Deci avem trei candidați, pentru interschimbarea de clasă dorită; am boldat aici, clasele acestora din ziua Mi
precum și acele clase din ziua Vi
la care are ore Bl2
în ziua Mi
.
Dacă am interschimba cu ET1
, trebuie să alegem clasa 7B
(și nu 5B
, fiindcă ET1
are deja oră la 5B
în ziua Mi
); cu Gg1
putem alege 7A
sau 9E
, iar cu LE2
trebuie să alegem 9B
.
Urmărind să uniformizăm și distribuția celui cu care interschimbă Bl2
, am alege fie Gg1
, fie LE2
; ținem seama și de faptul că ET1
are numai 10 ore și este mai convenabilă distribuția actuală (1 2 1 3 3)
, dacă ar fi să-i facem o zi liberă, mutând în vreo operație de interschimbare ulterioară, clasa de Lu
în ziua Mi
(sau invers).
Să zicem că alegem LE2
(clasa fiind în acest caz, unic determinată); interschimbarea decurge invocând change_zl()
de două ori consecutiv:
> R12 <- change_zl("Bl2", "9B", "Mi", "Vi") > R12 <- change_zl("LE2", "9B", "Vi", "Mi")
Actualizăm apoi, în urma interschimbării tocmai efectuate, tabelul distribuțiilor rămase neomogene – invocând imediat vcl_neunif()
; din cei 14, câți aveam inițial, au rămas 12 profesori – fiindcă prin interschimbarea efectuată, s-au omogenizat distribuțiile ambilor profesori implicați.
Repetând mecanismul descris, din aproape în aproape, pentru profesorii rămași – ajungem la un moment dat în situația în care nu mai găsim candidați pentru interschimbări (care să respecte regulile pe care ni le-am propus mai sus); de exemplu, noi ne-am „blocat” (procedând însă chiar mecanic, fără a căuta cel mai potrivite alegeri) când ne-au mai rămas 5 profesori cu distribuții neuniforme:
> vct_neunif() ET1 Gg2 Is2 LR1 Ps1 1 2 5 4 5 3 2 1 4 4 4 3 3 1 3 2 4 0 4 3 4 3 4 0 5 3 4 3 3 3
Distribuția lui Ps1
(cu două zile libere) poate fi considerată ca acceptabilă, acesta având numai 9 ore, la clase distincte; n-am reușit să facem „acceptabilă” și distribuția celor 10 ore ale lui ET1
, iar la ceilalți 3 profesori cam trebuie să ne mulțumim cu faptul că au distribuții cvasi-omogene (având între 3 și 5, sau 2 și 4 ore pe zi).
Dacă ne mulțumim așa, salvăm în R12i.RDS
și eventual încheiem – altfel, putem s-o luăm de la capăt (relansând brush.R
), schimbând însă ordinea în care abordăm profesorii rămași.
Bineînțeles… noi nu prea „ne mulțumim așa” – dar asta ar fi altă poveste (și cam veche): a vedea eventual, aplicația interactivă HTML+javaScript
postată pe Github (instanțiată pentru un alt orar, în /recast).
vezi Cărţile mele (de programare)