Considerăm orarul unei şcoli cu un singur schimb, dintr-un document PDF pe care l-am transformat (v. [1], [2]) în fişier .xlsx
; extragem datele din acest fişier şi le „normalizăm” într-un obiect tibble – separăm variabilele (profesor, clasă, zi, ora), eliminăm valorile nule, corectăm unele nume de clasă (înlocuim "11 F" cu "11F" şi "5" cu "5G", de exemplu) şi anonimizăm numele profesorilor (în variabila 'prof
' de tip factor):
# orar_orig.R library(tidyverse) sheets2lst_tb <- function(xlsx="") { require(readxl) xlsx %>% excel_sheets() %>% set_names() %>% map(read_excel, path = xlsx) # listă de 'tibble' asociate tablelor Excel } ltb <- sheets2lst_tb("General_profesori.xlsx") lmk <- rbind(ltb[[2]], ltb[[4]]) %>% filter(!is.na(`...1`)) # omite antetul dublu, "Luni... /r/n 1 2 ... 7..." Zile <- c('Lu','Ma','Mi','Jo','Vi') antet <- lapply(Zile, function(z) paste0(z, 1:7)) # "Lu1", "Lu2", etc. names(lmk) <- c("prof", unlist(antet)) # print(slice_sample(lmk, n=2)) # A tibble: 2 x 36 # prof Lu1 Lu2 Lu3 Lu4 Lu5 Lu6 Lu7 Ma1 Ma2 Ma3 Ma4 Ma5 # <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> #1 BUL… 11D 12A 10E NA 11A 6 NA 10A 5 9C 11C 9B #2 NEA… NA NA NA NA NA 9E 9E 10D 9A 11 F 12B NA # … with 23 more variables: Ma6 <chr>, Ma7 <chr>, Mi1 <chr>, Mi2 <chr>, etc. lmk[-1] <- lapply(lmk[-1], gsub, pattern=" ", replacement="", fixed=TRUE) # corectează "11 F" lmk <- lmk %>% pivot_longer(., cols=2:36, names_to="ZiOra", values_to="cls") %>% separate(ZiOra, c("zi", "ora"), sep=2) %>% filter(!is.na(cls)) %>% # (elimină valorile nule) mutate(ora = as.integer(ora), cls = ifelse(nchar(cls)==1, paste0(cls, "G"), cls)) # "5" devine "5G" # transformă 'prof' în "factor", cu nivelele "Pnn" srt <- sort(table(lmk$prof), decreasing=TRUE) lmk$prof <- factor(lmk$prof, levels=names(srt), ordered=TRUE) numePr <- c(paste0("P0", (1:9)), paste0("P", (10:nlevels(lmk$prof)))) # "Pnn" levels(lmk$prof) <- numePr #> slice_sample(lmk, n=2) ## A tibble: 2 x 4 # prof zi ora cls # <ord> <chr> <int> <chr> #1 P25 Jo 2 8G #2 P36 Mi 5 11A #> nrow(lmk) # [1] 884 (numărul de ore) saveRDS(lmk, file="orar_norm.RDS") # păstrează orarul normalizat
Numărul total de ore ar fi 884 (fiecare linie din lmk
înregistrează datele câte unei ore); de fapt, putem constata că există linii pe care diferă numai valoarea din coloana 'prof
' – deci numărul de ore care se desfăşoară într-o săptămână este mai mic de 884…
Tocmai de cuplaje, începem aici să ne ocupăm; la unele obiecte (de exemplu, limbi străine), doi profesori partajează într-o aceeaşi oră o aceeaşi clasă (despărţind-o în grupe de elevi); cum să ţinem seama de această situaţie, în programele noastre de repartizare pe zile şi respectiv, pe orele zilei, a lecţiilor (v. [1], [2])?
În [1] aveam chipurile noroc: cuplajele erau explicitate cumva chiar în orar, prin linii precum "P_5 Mi 4 11C/11D/\r\n
11E" – însemnând că în ora a 4-a din ziua "Mi", profesorul "P_5" partajează clasele indicate, cu alţi profesori (la care deasemenea găsim câte o astfel de linie). De data aceasta, valorile din celulele tablei Excel de la care am plecat sunt „curate” (cum şi trebuie să fie) – nu apar clase multiple (separate prin "/" sau "\r\n
"); dar cum evidenţiem atunci, cuplajele existente?
Profesorii cuplaţi au nume diferite în coloana 'prof
', dar au câte o aceeaşi valoare în celelalte trei coloane; prin split(list(
<coloane>))
separăm liniile în obiecte tibble care conţin fiecare, linii cu aceleaşi valori în coloanele indicate; cuplajele vor corespunde acelora dintre obiectele listei obţinute, care au cel puţin două linii:
cpl <- lmk %>% split(list(.$zi, .$ora, .$cls)) cpl <- map(seq_along(cpl), function(i) if(nrow(cpl[[i]]) > 1) cpl[[i]]) %>% compact() # elimină din listă valorile 'NULL'
map()
a parcurs după indici lista returnată de split()
şi a returnat o listă de aceeaşi lungime, înscriind NULL
pentru obiectele excluse (cele cu un singur rând); prin compact()
am eliminat în final, elementele nule. Avem, de exemplu:
> cpl[[1]] # A tibble: 2 x 4 prof zi ora cls <ord> <chr> <int> <chr> 1 P06 Mi 2 10A 2 P33 Mi 2 10A
cu această semnificaţie: "P06
" şi "P33
" intră într-o aceeaşi zi şi oră la clasa "10A
", lucrând (subînţelegem că în săli diferite) cu câte o grupă de elevi ai acestei clase.
Transformăm lista 'cpl
' într-un tibble care conţine pe fiecare linie un vector de profesori (convertind prin as.character()
, întregii asociaţi acestora prin factor-ul 'prof
'), clasa şi numărul de ore pe care aceştia sunt cuplaţi:
cpl <- map_df(seq_along(cpl), function(i) tibble(cup=paste(c(as.character(cpl[[i]]$prof)), collapse="-"), cls=cpl[[i]]$cls[1])) %>% count(cup, cls) #> cpl ## A tibble: 20 x 3 # cup cls n # cup cls n # <chr> <chr> <int> # 1 P01-P02 10A 3 #11 P06-P33 10F 1 # 2 P01-P02 11A 3 #12 P06-P33 9A 1 # 3 P01-P02 11B 3 #13 P06-P33 9B 1 # 4 P01-P02 12A 3 #14 P06-P33 9C 1 # 5 P01-P02 9A 3 #15 P08-P11 12E 1 # 6 P06-P33 10A 1 #16 P08-P25 12E 2 # 7 P06-P33 10B 1 #17 P08-P47 12E 5 # 8 P06-P33 10C 1 #18 P11-P44 11E 6 # 9 P06-P33 10D 1 #19 P34-P07 10E 5 #10 P06-P33 10E 1 #20 P34-P09 9E 5
Deci, în cazul de aici, avem 20 de cuplaje (care angajează 12 profesori), de cel mai simplu tip: doi profesori partajează o singură clasă. "P01
" şi "P02
" sunt cuplaţi pe câte 3 ore la fiecare dintre clasele 10A
, 11A
, 11B
, 12A
şi 9A
; "P06
" şi "P33
" cuplează câte o oră la clasele a 10-a şi la 9ABC
; la clasa 12E
, "P08
" cuplează cu "P11
" pe o oră, cu "P25
" pe două ore şi cu "P47
" pe 5 ore; "P11
" cuplează şi cu "P44
", pe 6 ore, la clasa 11E
; în sfârşit, "P34
" cuplează cu "P07
" pe 5 ore la 10E
şi cu "P09
" tot pe 5 ore, la 9E
.
Ca idee, „profesorul” fictiv "P01-P02
" va prelua orele partajate de "P01
" şi "P02
"…
Din orarul iniţial nu ne interesează decât datele referitoare la încadrarea profesorilor: câte ore are fiecare şi la care clase; plecând de la încadrarea respectivă, vrem să generăm (prin programele din [1], [2]) o repartizare cât mai omogenă a orelor pe zilele săptămânii şi apoi, orarele propriu-zise, corespunzătoare fiecărei zile.
Cuplajele prevăzute iniţial în încadrare contrazic din start, condiţia esenţială asumată într-un program de generare a unui orar: doi profesori nu pot intra simultan, la o aceeaşi clasă. Am avea două soluţii de conciliere: una practică – eliminăm pur şi simplu cuplajele, generăm orarul „de bază” şi ulterior, adăugăm interactiv şi cuplajele; şi o soluţie de investigat mai departe – mascăm cumva cuplajele, asociind fictiv orele respective unor noi profesori (sau unor noi clase).
Dacă am avea cuplaje mai complicate – în care doi (sau mai mulţi) profesori partajează nu o singură clasă, ci două sau mai multe – atunci probabil că ar trebui să optăm pentru înfiinţarea de noi clase; noi vizăm totuşi cazul cel mai obişnuit de cuplaje, pentru care ni se pare cel mai potrivit să înfiinţăm profesori fictivi.
Ca idee, dacă Px
şi Py
sunt cuplaţi pe n ore la clasa Q
, atunci depistăm liniile din setul lmk
pe care în coloana $prof
apare Px
sau Py
şi în coloana $cls
apare Q
, iar pe acele dintre aceste linii care au câte o aceeaşi valoare în câmpurile $zi
şi $ora
, înscriem ca „profesor” (fictiv) "Px-Py
"; să observăm că astfel, vor fi afectate 2×n linii – deci mai trebuie să şi eliminăm n dintre acestea.
La implementarea acestei idei avem de ţinut seama de faptul că variabila lmk$prof
este deja de tip factor ordonat (şi am avea de modificat nivelele deja stabilite ale acestuia); noi preferăm să folosim operaţii generale "_join()
", care dacă este cazul, transformă în mod implicit tipurile de date (în loc de "factor" <ord>
vom avea <chr>
).
Pentru o linie indicată din cpl
, următoarea funcţie produce un tabel tibble care conţine cele 2×n linii din lmk
descrise mai sus (şi îi adăugăm o coloană de cuplare):
trace_cpl <- function(i) { pr <- unlist(strsplit(as.character(cpl[i, 1]), "-")) q <- cpl[i, 2] ls2 <- lmk %>% filter(cls %in% q & prof %in% pr) %>% split(list(.$zi, .$ora)) trc <- map_df(seq_along(ls2), function(j) if(nrow(ls2[[j]]) > 1) ls2[[j]]) trc %>% mutate(cpl[i, 1]) # înscrie profesorul fictiv, pe o nouă coloană } print(trace_cpl(16)) ## A tibble: 4 x 5 # prof zi ora cls cup # <ord> <chr> <int> <chr> <chr> #1 P08 Ma 2 12E P08-P25 #2 P25 Ma 2 12E P08-P25 #3 P08 Jo 3 12E P08-P25 #4 P25 Jo 3 12E P08-P25
Lui P08-P25
va trebui să-i punem 2 ore (nu 4) la clasa 12E
.
Aplicăm trace_cpl()
tuturor liniilor din cpl
şi reunim prin map_df()
tabelele rezultate, obţinând obiectul tibble del
; prin anti_join()
, eliminăm din lmk
liniile aduse în del
(ignorând câmpul final del$cup
), apoi înlocuim valorile din del$prof
cu acelea din del$cup
şi eliminăm coloana del$cup
; în final, prin full_join()
adăugăm în lmk
liniile din del
şi prin distinct()
eliminăm liniile duble (încât din fiecare 2×n linii care înregistrau orele cuplate în del
, rămân n linii):
del <- map_df(1:nrow(cpl), trace_cpl) # print(del) lmk <- anti_join(lmk, del[-5]) # implicit, factorul $prof este degradat la <chr> del$prof <- del$cup # fixează profesorii fictivi pe orele cuplate del$cup <- NULL lmk <- full_join(lmk, del) %>% distinct() # lmk %>% print(n=Inf) ## 836 ore
Iniţial, lmk
conţinea linii cu câte o aceeaşi valoare în câmpurile $zi
, $ora
şi $cls
, corespunzătoare cuplajelor; acum, introducând profesori fictivi pe orele cuplate, acest defect a fost îndepărtat şi numărul de linii din lmk
este exact numărul total de ore (836) din săptămână.
Eliminăm în sfârşit, câmpurile $zi
şi $ora
; apoi, convertim iarăşi $prof
în factor ordonat (descrescător, după numărul de ore ale profesorilor, incluzând şi pe cei fictivi):
lmk <- lmk %>% select(prof, cls) srt <- sort(table(lmk$prof), decreasing=TRUE) lmk$prof <- factor(lmk$prof, levels=names(srt), ordered=TRUE) lmk <- lmk %>% arrange(prof) saveRDS(lmk, file="lmk.RDS")
Ilustrăm lmk
prin 5 linii alese aleatoriu:
> print(slice_sample(lmk, n=5)) # A tibble: 5 x 2 prof cls <ord> <chr> 1 P31 10A 2 P12 10D 3 P34-P07 10E 4 P27 12D 5 P32 7G
Desigur – fie în mod interactiv, fie direct în programul de repartizare pe zile a orelor din "lmk.RDS
" – va trebui să corelăm orele plasate unui profesor fictiv, cu acelea plasate în aceeaşi zi celor doi profesori pe care îi cuplează; analog ulterior, pentru programul de repartizare pe orele zilei, a orelor plasate într-o aceeaşi zi.
Programul "distribute_by_days.R
" (redat şi reluat anterior de mai multe ori), prin funcţia principală alloc_by_class()
, asigură distribuirea lecţiilor prof
|cls
pe zilele de lucru, angajând o singură condiţie: distribuţiile individuale, pentru profesorii cu măcar 10 ore, să fie „cvasi-omogene” (pentru fiecare, numărul de ore pe zi nu diferă de la o zi la alta, cu mai mult de 2 ore); punând această singură condiţie, obţinem o distribuţie pe zile într-un timp foarte scurt (în general, 2-5 minute). Rămâne celui care face orarul şcolii, să regleze interactiv distribuţia obţinută, pentru a ţine seama de diversele condiţii concrete, specifice fiecărei şcoli (profesorul cutare vine numai în cutare zile; cutare trebuie să aibă liber în cutare zile; etc., etc.).
În cazul cuplajelor, am avea această condiţie: în oricare zi, numărul de ore alocate cuplului şi oricăruia dintre parteneri să nu depăşească 6 ore (sau 7 ore, la unele clase); considerăm că şi această condiţie trebuie lăsată în seama reglării interactive ulterioare – pentru a lăsa celui care face orarul libertatea de a decide în funcţie de condiţiile concrete existente, cum să plaseze orele cuplate (de exemplu, poate că orele de „laborator” trebuie comasate în câte o anumită zi, la fiecare clasă).
Pentru încadrarea din "lmk.RDS
", după ce am obţinut prin alloc_by_class()
o distribuţie (cvasi-omogenă) pe zile a lecţiilor respective, am folosit aplicaţia interactivă /Recast (v. şi github), obţinând (în cam 30-40 minute) o distribuţie omogenă acceptabilă:
prof | Lu | Ma | Mi | Jo | Vi |
---|---|---|---|---|---|
P03 | 10F 9B 11E 9E 10E 9C | 9B 10B 12C 9C 10C 9D | 9B 10B 11C 10D 9F | 12B 11C 9F 9D 11F 10C | 11E 9E 12E 8G 9C |
P04 | 12F 5G 10E 11D 12A | 12F 11C 5G 10E 11D | 12F 11C 10E 11D 12A | 12F 11C 5G 10E 11D 12A | 12F 11C 5G 10E 12A |
P05 | 9A 10B 8G 10C 11B | 10F 9A 10B 8G 10C | 10F 10B 11B 8G 10C | 9A 11B 9D 8G 10C | 10B 11B 9D 8G 9A |
P10 | 9B 11E 11D 9C 9F | 9B 9E 10E 9C 10D | 9E 9F 10E 9C 12D | 9B 12E 10D 9C 12D | 9B 11E 12E 11D |
P12 | 11B 12F 10D 10A | 11B 12F 10D 11D 12D | 12C 5G 10D 9A 10A | 12B 12C 5G 10D 9A | 12B 12F 5G 12D 11D |
P13 | 11B 9E 8G 10A | 9A 10D 9C 12A 7G | 9B 12C 12E 10E 12B | 10B 11E 11A 12D | 11C 11A 9D 10C 11D |
P14 | 9A 8G 11F 10A | 9A 11E 8G 11F 10A | 9A 11E 8G 11F 10A | 9A 11E 8G 11F | 9A 11E 8G 11F |
P15 | 10B 12E 12D 10A | 11E 12F 12E 12D 10C | 11E 12F 12E 11D 12D | 12F 12E 11D 12D | 12E 11D 12D 11F |
P16 | 9B 12B 10D 10C | 12B 10D 6G 10C 10F | 12B 11B 6G 10C | 9B 11B 10C 9F | 10F 9B 11B 9F 10C |
P17 | 11C 5G 12A 12B | 12B 11C 5G 10A 12A | 11C 5G 10A 12A | 12B 11C 5G 10A 12A | 12B 5G 10A 12A |
P18 | 10B 12C 11C 9D | 10B 12C 11C 9D | 10B 12C 11C 9C | 12F 9E 10E 11F 9C | 12C 9E 10E 9C |
P19 | 12C 12E 10D 9D | 12E 10D 9D 11B | 11B 12C 10D 9D | 11B 12C 12E 10D 9D | 11B 12C 12E 10D |
P07 | 12C 12F 10C 9C | 9B 12F 10A 10C | 9B 10A 12A 12F | 5G 8G 9C 12A | 12F 5G 8G 12C |
P09 | 10B 11E 10D 11F | 11C 10D 11F 7G | 9A 12B 11C 11F | 9A 12B 11C 11D | 10B 11E 11D 7G |
P20 | 10F 12F 8G 11A | 12C 5G 8G 10A | 12E 5G 10A 10C | 10B 9F 12D 10C | 10B 9F 10E 12D |
P21 | 12E 10D 10A 7G | 10F 11E 12E 7G | 10F 11E 12E 9D | 10F 11E 10D 6G | 12E 10D 10C 9D |
P22 | 9B 10B 12B 12D | 9B 12B 11A 12D | 10B 12B 11A 12D | 9B 11A 12D 10B | 9B 12B 11A 12D |
P23 | 12C 11A 9F 11F | 12B 11B 9F 11F | 9B 12F 9F 11F | 12F 8G 11F 12A | 9A 10B 12F 8G |
P24 | 9A 12B 6G 7G | 11B 9E 9D 11D | 10D 11D 9C 7G | 9B 11E 6G 12A | 11C 6G 11F |
P26 | 11E 12F 9D 11F | 9A 11E 12F 9D | 11E 9E 9F 9D | 12C 9E 9F 10F | 10F 10B 11F |
P08 | 9F 6G 12D | 10F 11B 9F 12D | 10F 11B 9D 6G | 10F 12E 9D | 10F 9F 9D |
P11 | 10F 9B 9C | 10F 9F 9E 12A | 9F 9D 12A 7G | 9E 9D 7G | 9B 9D 9C |
P25 | 11A 11F 10C | 10B 11A 8G | 10B 8G 10E 11F | 11C 10E 11F 6G | 11C 6G 10C |
P27 | 9E 10E 11D 12D | 9E 5G 12D | 9E 5G 11D 10E | 11C 11D 12D | 10E 11D 12D |
P28 | 11B 11C 10E | 9B 10E 11D 12A | 5G 6G 11D | 11A 10D 11D 9C | 10D 9C 10A |
P29 | 12B 12C 9D | 10B 12C 10C 11A | 9A 10B 10C | 9A 10B 12B 12C | 12B 11B 12C |
P30 | 12B 11C 12A | 12B 11C 10A 8G | 12B 12C 11C 11A | 12B 12C 8G | 12B 12C 10A |
P31 | 9B 11C 10D | 11C 6G 9C | 9B 6G 9C 7G | 9B 10A 7G | 9B 11C 10A 12A |
P06 | 12F 5G 11F | 12F 9F 11D 12D | 10F 8G 6G | 12E 9D 7G | 9E 11F 11E |
P32 | 9A 10B 7G | 9B 10E 9C 10B | 9B 9C 10C | 11B 9C 10C | 9A 10B 7G |
P01-P02 | 11B 10A 12A | 9A 11A 12A | 9A 11A 12A | 9A 11B 11A 10A | 11B 10A |
P01 | 11A 12A | 11A 12A 10A | 11A 12A 6G | 5G 10A | 11A 10A 12A |
P02 | 9A 11B 11D | 9A 11B 11D | 11B 12D | 11B 12F | 9A 11B 7G |
P35 | 11A 10C 10F | 11E 10E 10A | 11B 11E | 10B 11F | 10D 11C |
P36 | 10A 12A 9A | 9A 11A 10A | 11A 12A 10A | 9A 11A 12A | |
P37 | 9F 9C | 9D 7G | 12C 9D | 9B 9A | 9F 12A 12B |
P38 | 9E 10C | 9E 9C | 9E 10C 9C | 9E 9C | 9C 10C |
P39 | 9E 10E 9D | 9F 11F | 12F 10D 11F | 10F 7G | |
P06-P33 | 10F 9C | 9A 10E | 10B 10A 10C | 9B 10D | |
P40 | 11A 7G | 11A 7G | 11A 7G | 7G | 11A 7G |
P41 | 10F 7G | 10F 7G | 10F 7G | 10F 7G | |
P42 | 12C 6G | 12C 6G | 12C 6G | 12C 6G | |
P33 | 9F 9D 7G | 9E 8G | 5G 6G | ||
P11-P44 | 11E | 11E | 11E | 11E 11E | 11E |
P43 | 9F 11F | 9F | 9F | 12F 9F | |
P45 | 10F 5G 9F 6G | 11F 12F | |||
P46 | 5G 8G 10E | 9E 9F 10F | |||
P08-P47 | 12E | 12E | 12E | 12E | 12E |
P34-P07 | 10E | 10E | 10E | 10E | 10E |
P34-P09 | 9E | 9E | 9E | 9E | 9E |
P48 | 10F 9E 10D | 9F 9D | |||
P49 | 12D | 12B 12D | 12D 10C | ||
P50 | 6G | 6G | 6G | 6G | 6G |
P34 | 11A 10E | 11A 9E | |||
P51 | 8G 7G | 7G 8G | |||
P52 | 10D 9E | 9E 10D | |||
P53 | 10F 10E | 10F 10E | |||
P54 | 11F 12D | 12F 11D | |||
P55 | 8G | 8G 7G | |||
P56 | 5G 8G 6G | ||||
P08-P25 | 12E | 12E | |||
P57 | 12E | 12E | |||
P58 | 11D | 11D | |||
P59 | 5G 6G | ||||
P08-P11 | 12E | ||||
P60 | 9C | ||||
P61 | 8G | ||||
P62 | 7G |
Pentru această distribuţie am respectat o serie de principii general valabile.
Cele 836 de lecţii sunt repartizate uniform pe zile: (167 167 167 168 167); pentru profesorii cu măcar 10 ore, distribuţiile individuale sunt omogene (cu două excepţii, la P36
şi P39
) – de exemplu, pentru 16 ore avem distribuţii ca (4 3 3 3 3).
Bineînţeles că pentru fiecare clasă, distribuţia orelor pe zile este uniformă (numărul de ore pe zi diferă cu cel mult 1, de la o zi la alta).
Exceptând P01
şi P02
(care sunt cuplaţi pe câte 3 ore la 5 clase) şi poate, alte cupluri ("P11-P44
", care la clasa 11E
are 6 ore) – toţi profesorii intră câte o singură dată pe zi, la fiecare dintre clasele respective; în măsura în care această cerinţă nu este încălcată, profesorii care au puţine ore au câte un anumit număr de zile libere (P50
are numai 5 ore, dar toate la aceeaşi clasă – deci nu are zi liberă; P55
are numai 3 ore, dar 2 ore sunt la o aceeaşi clasă – deci distribuim cele 3 ore în două zile, nu într-una singură; P56
are 3 ore, la clase diferite – încât le-am putut plasa într-o singură zi).
Desigur că în realitate, plecând nu de la „principii”, ci de la „în ce zile puteţi veni” – distribuţia redată mai sus este de neacceptat; probabil că P50
va zice aşa: „am numai 5 ore, deci trebuie să mi le puneţi în 2 zile, anume cutare şi cutare” (încât P50
ar trebui să facă la clasa 6G
, 2 ore într-o cutare zi şi 3 ore într-o altă cutare zi).
Şi acceptând o excepţie de la „principii”, va trebui apoi să înghesuim orele profesorilor, încât aceştia să şi le facă în cât mai puţine zile – fără a mai lua în seamă şi interesele fireşti ale elevilor, privitoare la distribuţia echilibrată a obiectelor pe parcursul săptămânii.
Programul anterior daySchoolSchedule.R
preia din repartiţia pe zile obţinută mai sus, lecţiile repartizate într-o aceeaşi zi şi produce orarul propriu-zis al acelei zile – dar angajează iarăşi, o singură condiţie, privitoare la numărul de ferestre; însă în acest caz, s-ar cuveni probabil, ca instrumentarea cuplajelor existente să fie făcută chiar în program (în loc de a o lăsa iarăşi, în seama unei intervenţii interactive ulterioare).
Cele două programe de repartizare vizate mai sus, angajând câte o singură condiţie (aceea care şi este esenţială: omogenitatea distribuţiilor individuale şi respectiv, limitarea numărului de ferestre), îşi produc rezultatele foarte rapid; noi susţinem în continuare, că diversele condiţii particulare (inclusiv, cele privitoare la cuplaje) trebuie lăsate în seama unor intervenţii interactive ulterioare.
Totuşi, merită sau nu – vom încerca mai departe să modificăm daySchoolSchedule.R
, încât să ţinem seama şi de cuplajele existente pe ziua respectivă.
vezi Cărţile mele (de programare)