Termen de predare:
Pentru fiecare zi (24 de ore) de întârziere, se vor scădea 10 puncte din nota acordată, până la atingerea deadline-ului hard.
Dacă aveți nelămuriri, puteți să ne contactați pe forumul dedicat temei de casă nr. 2 sau pe canalul Temei 2.
Nu se acceptă întrebări în ultimele 24 de ore înainte de deadline.
Ne propunem să construim un sistem care simulează Epoch Converter.
Un Unix Timestamp este un mod standardizat de reprezentare a unui moment în timp, foarte folosit în multe aplicații, framework-uri, și sisteme de operare. Un Unix Timestamp este definit ca numărul de secunde care au trecut de la 1 ianuarie 1970, ora 00:00:00 (in timezone-ul UTC, fostul GMT, numit popular și “ora Angliei”).
0
corespunde datei 1 ianuarie 1970, ora 00:00:00
3659
corespunde datei 1 ianuarie 1970, ora 01:00:59
1703201916
corespunde datei 21 decembrie 2023, ora 23:38:36
Pentru această temă trebuie să porniți de la scheletul de cod de aici: tema2_schelet.zip.
Implementați în fișierul timelib.c
funcția:
TTime convertUnixTimestampToTime(unsigned int timestamp)
Funcția trebuie să returneze ora, minutul și secunda corespunzatoare timestamp-ului primit, sub forma unei structuri TTime:
typedef struct { unsigned char hour; unsigned char min; unsigned char sec; } TTime
timestamp=0 => hour=0; min=0; sec=0 timestamp=3659 => hour=1; min=0; sec=59 timestamp=1703201916 => hour=23; min=38; sec=36
Hour
ia valori între 0 și 23; min
ia valori între 0 și 59; sec
ia valori între 0 și 59.
Implementați în fișierul timelib.c
funcția:
TDate convertUnixTimestampToDateWithoutLeapYears(unsigned int timestamp)
Funcția trebuie să returneze ziua, luna și anul corespunzătoare timestamp-ului primit, sub forma unei structuri TDate:
typedef struct { unsigned char day; unsigned char month; unsigned int year; } TDate
timestamp=0 => day=1; month=1; year=1970 timestamp=3659 => day=1; month=1; year=1970 timestamp=1703201916 => day=3; month=1; year=2024
Day
ia valori între 1 și 31; month
ia valori între 1 și 12; year
ia valori de la 1970 în sus.
Implementați în fișierul timelib.c
funcția:
TDate convertUnixTimestampToDate(unsigned int timestamp)
Funcția trebuie să returneze ziua, luna și anul corespunzătoare timestamp-ului primit, sub forma unei structuri TDate ca la taskul anterior, însă luând în considerare anii bisecți. Un an bisect este un an cu 366 de zile (luna februarie are 29 de zile în loc de 28). Anii bisecți sunt toți anii divizibili cu 4 (e.g. 2004, 2008, 2012) cu excepția anilor care sunt multipli de 100 dar nu și multipli de 400 (exemplu: anii 2000 și 2400 sunt bisecți, dar anii 2100, 2200, 2300 nu sunt).
timestamp=0 => day=1; month=1; year=1970 timestamp=3659 => day=1; month=1; year=1970 timestamp=1703201916 => day=21; month=12; year=2023
Implementați în fișierul timelib.c
funcția:
TDateTimeTZ convertUnixTimestampToDateTimeTZ(unsigned int timestamp, TTimezone *timezones, int timezone_index)
Funcția primește un Unix Timestamp, un vector de timezone-uri, și un index care definește timezone-ul din vector ce trebuie folosit. Un timezone (fus orar) este reprezentat de o structură TTimezone, cu următoarele componente:
typedef struct { char name[5]; signed char utc_hour_difference; } TTimezone
Funcția trebuie să returneze o structură TDateTimeTZ, cu următoarele componente:
typedef struct { TDate date; TTime time; TTimezone *tz; } TDateTimeTZ
Pentru această funcție, la conversia din Unix Timestamp în formatul Date+Time, trebuie luată în considerare diferența de timp impusă de timezone. Spre exemplu, timestamp-ul 1703201916
corespunde datei 21 decembrie 2023, ora 23:38:36
dacă acesta este considerat în timestamp-ul UTC (echivalent cu GMT), pentru care utc_hour_difference
este 0. Însă același timestamp, într-un timezone în care utc_hour_difference
este 2 (spre exemplu, EET) va corespunde datei 22 decembrie 2023, ora 01:38:36
(2 ore mai târziu). Același timestamp, într-un timezone în care utc_hour_difference
este -5, va corespunde datei 21 decembrie 2023, ora 18:38:36
.
[(“UTC”, 0); (“EET”, 2); (“PST”, -8)]
Exemple de rulare:
timestamp=1703201916, timezone_index=0 => 21-12-2023 23:38:36 timestamp=1703201916, timezone_index=1 => 22-12-2023 01:38:36 timestamp=1703201916, timezone_index=2 => 21-12-2023 15:38:36
-13 < utc_hour_difference < 15
Implementați în fișierul timelib.c
funcția:
unsigned int convertDateTimeTZToUnixTimestamp(TDateTimeTZ)
Funcția primește un TDateTimeTZ așa cum a fost definit mai sus și execută operația inversă, calculând Unix Timestamp-ul corespunzător.
22 decembrie 2023, ora 01:38:36
în timezone EET (UTC+2) va corespunde timestamp-ului 1703201916
.
[(“UTC”, 0); (“EET”, 2); (“PST”, -8)]
Exemple de rulare:
21-12-2023 23:38:36 (UTC) => 1703201916 22-12-2023 01:38:36 (EET) => 1703201916 21-12-2023 15:38:36 (PST) => 1703201916
Implementați în fișierul timelib.c
funcția:
void printDateTimeTZ(TDateTimeTZ datetimetz)
Funcția afișează la stdout datetime-ul primit, în următorul format: [data] [luna (cuvânt)] [anul], [ora]:[minutul]:[secunda] [timezone name] (UTC[+/-][timezone utc hour diff])
1 ianuarie 1970, 05:00:00 UTC (UTC+0) 22 decembrie 2023, 01:38:36 EET (UTC+2) 21 decembrie 2023, 15:38:36 PST (UTC-8)
Printr-o rețea de calculatoare se trimite un vector de obiecte de tip “dată” (zi, lună, an). Din motive de economisire a spațiului, aceste date sunt memorate pe biții unui unsigned int (presupunem unsigned int de 32 de biți), în următorul format:
Biți nefolosiți | Anul | Luna | Ziua |
---|---|---|---|
17 biți | 6 biți | 4 biți | 5 biți |
Astfel, în cadrul unui unsigned int:
00001
) și 31 (11111
)0001
) și 12 (1100
)000000
) ce reprezintă anul 1970, și 63 (111111
) ce reprezintă anul 2033
Scrieți un program (în fișierul bitpacking.c
) care citește:
Programul trebuie să afișeze la stdout datele citite, câte una pe linie, sortate în ordine cronologică, în formatul [zi] [lună] [an]
(exemplu: 21 decembrie 2023
).
Modificați programul din fișierul bitpacking.c
pentru a rezolva acest task atunci când se citește 8 pentru numărul taskului.
O problemă majoră a packing-ului pe biți așa cum a fost definit la taskul 7 este că nu e foarte eficient. Deși sunt necesari doar 15 biți (6+4+5) pentru memorarea unei date, sunt folosiți cei 32 de biți ai unui unsigned int. Pentru a rezolva această problemă, vom împacheta datele la un loc folosind aceleași valori unsigned int. Astfel:
Pentru un plus de realism, dorim să simulăm și cazul în care pe rețea există perturbații care alterează datele transmise. Pentru asta, vom avea câte un bit de control (separat de împachetarea descrisă mai sus) pentru fiecare unsigned int citit. Acest bit de control va fi definit ca B1%2
, unde B1
reprezintă numărul de biți de 1 din unsigned int-ul respectiv.
Spre exemplu:
00000000 00000000 00000000 00000000
, bitul de control va fi 0 (sunt 0x biți egali cu 1 în acest int)01010101 01010101 01010101 01010101
, bitul de control va fi 0 (sunt 16x biți egali cu 1 în acest int, iar 16 este număr par - 16%2 == 0
)01010101 01010101 01010101 01010111
, bitul de control va fi 1 (sunt 17x biți egali cu 1 în acest int, iar 17 este număr impar - 17%2 == 1
)Biții de control vor fi și ei împachetați într-un șir de unsigned int-uri de control. Astfel:
Biții de control vor fi folosiți astfel:
B1
) și se calculează B1%2
Modificați programul de la task 7 (în fișierul bitpacking.c
) astfel încât, atunci când numărul taskului citit este 8, să ruleze cu următoarele modificări:
Programul trebuie să afișeze la stdout datele citite (dar numai cele ai căror biți sunt în totalitate numai în unsigned int-uri care nu sunt corupte), câte una pe linie, sortate în ordine cronologică, în același format ca la taskul 7.
Ne propunem să creăm un sistem de management de evenimente care găsește automat un interval de timp în care persoanele ce trebuie să participe la eveniment sunt libere.
Scrieți un program (în fișierul planner.c
) care:
Programul trebuie să găsească primul interval temporal în care evenimentul se poate organiza astfel încât minim F persoane să fie disponibile pe întreaga durată a evenimentului. Dacă nu există niciun interval în care să se poată organiza evenimentul, programul trebuie să afișeze “imposibil”. Dacă se găsește un interval în care evenimentul se poate ține, atunci programul trebuie să afișeze P linii (câte una pentru fiecare dintre cele P persoane, sortate alfabetic după nume), cu următorul conținut:
[nume]: [data]
(data fiind reprezentată sub forma an, lună, zi, oră, minut, secundă, timezone - în același format ca la taskul 6) evenimentului, în timezone-ul acestei persoane
1 UTC 0 3 Alin UTC 1 2023 12 20 12 5 Vlad UTC 3 2023 12 20 12 1 2023 12 20 14 2 2023 12 20 16 1 Traian UTC 1 2023 12 20 12 1 2 3
Pentru inputul de mai sus, outputul trebuie să fie:
Alin: 20 decembrie 2023, 14:00:00 UTC (UTC+0) Traian: invalid Vlad: 20 decembrie 2023, 14:00:00 UTC (UTC+0)
Explicație:
Încă un exemplu de input pentru care rezultatul va fi același, dar de data asta persoanele se află în timezone-uri diferite:
3 UTC 0 EET 2 PST -8 3 Alin UTC 1 2023 12 20 12 5 Vlad EET 3 2023 12 20 14 1 2023 12 20 16 2 2023 12 20 18 1 Traian PST 1 2023 12 20 4 1 2 3
Pentru acest task, trebuie să aveți punctajul maxim pe taskul 9 și să nu aveți memory leaks la verificarea folosind utilitarul valgrind pe acesta.
Utilitarul se va rula folosind urmatoarea comanda:
valgrind --tool=memcheck --leak-check=full --error-exitcode=1 ./planner
La fel ca la temele precedente, există o depunctare de până la -20p pentru coding style. Checkerul verifică coding style-ul în mod automat.
Checker: t2_checker.zip
Tema va fi trimisă folosind Moodle, cursul Programarea Calculatoarelor (CB & CD), activitatea “Tema 2”.
Toate temele sunt testate în mod automat pe Moodle.
Arhiva temei se va încărca folosind formularul de submisie (butonul Add submission.
Rezultatele vor fi disponibile în secțiunea Feedback - nota apare la linia Grade, iar outputul checkerului și erorile apar la sectiunea Feedback comments. Dacă apare un buton albastru în formă de plus, trebuie să dați click pe el pentru a afișa întregul output al checkerului.
Citiți cu atenție informațiile afișate în Feedback pentru a vă asigura că tema a fost rulată cu succes; o eroare comună este dată de faptul că conținutul arhivei nu respectă structura dorită (ex. fișierele sunt într-un alt director).
Punctajul final al temei este afișat la linia Grade și la finalul outputului din checker.
Conținutul arhivei trebuie să fie următorul:
Lista nu este exhaustivă.