Tema 1 - The Classics

Changelog:

  • 7.11.2024: pagina creata
  • 8.11.2024: clarificari enunt si mici completari
  • 11.11.2024: adaugat arhiva schelet si linkuri lipsa
  • 13.11.2024: clarificari pentru task 1: indexarea coloanelor
  • 13.11.2024: teste corectate

Responsabili:

Termen de predare:

  • 27.11.24 - Soft
  • 29.11.24 - Hard

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.

Introducere

In cadrul acestei teme ne propunem sa implementam un simulator al unui joc arcade (pacanea), in care o serie de simboluri vor fi amplasate intr-un tablou bidimensional. Va exista un cadran in interiorul caruia simbolurile vor putea forma combinatii valide, predefinite, care vor fi explicate in continuare, iar fiecare combinatie va avea un scor asociat. Scopul jocului este de a calcula scorul la un moment dat, avand in vedere ca fiecare rotire are un cost, iar jucatorul dispune de un anumit buget.

Se doreste exersarea urmatoarelor concepte:
  • folosirea corecta a functiilor pentru lucrul cu memoria
  • parcurgerea unui tablou bidimensional
  • implementarea unor algoritmi simpli de parcurgere si calcul

Întrebări

Dacă aveți nelămuriri, puteți să ne contactați pe forumul dedicat: pe Mudal sau pe Teams.
Nu se acceptă întrebări în ultimele 24 de ore înainte de deadline.

Atenție:

  • Citiți cu atenție tot enunțul temei.
  • Respectați întocmai regulile de încarcare a arhivei. Dacă uitați să includeți fișierele sursă sau Makefile-ul în arhivă, veți primi 0 pe temă.
  • Respectați întocmai instrucțiunile de scriere a fișierului Makefile. Checkerul folosește acest fișier pentru a vă rula tema. Dacă el nu este scris corect, veți primi 0 pe temă chiar dacă codul sursă este ok.
  • La trimiterea arhivei pe Moodle, tema vă este corectată automat, pe loc. Verificați secțiunea “Feedback” pentru a afla punctajul. Dacă vă apar erori și/sau nu apare punctajul obținut (în format numeric e.g. 85/100) înseamnă că tema voastră nu a fost rulată și veți primi 0 pe temă dacă nu rezolvați eroarea.
  • Puteți retrimite tema de oricate ori vreți înainte de expirarea deadline-ului. Se va lua în considerare numai ultima variantă trimisă.

Enunt

Gigel

Gigel este pasionat de jocuri de noroc si se afla intr-o situatie financiara destul de precara. Gigel ar dori sa stie ce are de facut ca sa castige o suma considerabila. El a auzit ca 99% din jucatori se opresc chiar inainte sa castige, asa ca s-a decis sa nu faca parte din aceasta statistica, venind la voi cu urmatoarea idee: un simulator de pacanele. El a mai mentionat si ca nu are incredere in demo-urile de pe diverse aplicatii ale caselor de pariuri, deoarece acestea ii ofera niste castiguri suspecte.

Specificatii

Vor exista un numar N de linii si respectiv M de coloane, reprezentand toate simbolurile aflate in acest simulator; coloanele se pot misca independent una de cealalta, iar simbolurile de pe o coloana raman intotdeauna in aceeasi pozitie fata de celelalte simboluri de pe aceeasi coloana (adica [1, 2, 3, 4] poate deveni, de exemplu, [3, 4, 1, 2], dar nu si [1, 3, 2, 4]), conform miscarii de rotatie a coloanelor. Vor exista cel mult 10 simboluri distincte, pe care le vom numerota convenabil de la 0 la 9 (practic fiecare cifra este codificarea unui simbol).

Asa cum a fost mentionat mai sus, nu toate simbolurile din matrice pot forma combinatii castigatoare la un moment dat, ci doar cele aflate in interiorul unui cadran predefinit. Cadranul este un dreptunghi 3 x M (adica se intinde pe toata latimea matricii, si contine cate 3 simboluri din fiecare coloana). Consideram ca acest cadran se afla chiar in “capatul de sus” al matricii, adica continand mereu primele 3 linii ale matricii, si nu poate fi deplasat. Exemplu ilustrativ:
  N = 8, M = 4;
  1 2 3 4
  1 6 2 5
  3 4 2 2
  9 0 1 3
  5 5 5 2
  1 7 8 8
  3 3 6 5
  7 7 7 7
Cadranul contine primele 3 linii, adica simbolurile [ [1, 2, 3, 4], [1, 6, 2, 5], [3, 4, 2, 2] ]

Cerinte

Gigel are un numar de feature-uri pe care doreste sa le aiba acest simulator, dupa cum urmeaza:

Task 1. Spin the... pixels? (10p)

Se doreste rotirea unei coloane specificate. De exemplu: daca avem o matrice cu 5 linii si 3 coloane, si dorim sa rotim coloana a doua cu 3 pozitii, operatia dorita inseamna permutarea simbolurilor de pe coloana a doua cu trei pozitii in jos, pastrand prima si ultima coloana neschimbate. Permutarea are loc in sens natural, de sus in jos, iar simbolurile care “ies din matrice” vor fi mutate la inceputul acesteia. Exemplu ilustrativ:

N = 5, M = 3;
1 2 3
4 5 6
7 8 9
0 1 2
3 4 5
c = 1, r = 3 // indexare de la 0 pentru coloane

Rotirea coloanei a doua cu 3 pozitii inseamna:

1 8 3
4 1 6
7 4 9
0 2 2
3 5 5

Task 2. The game might be rigged, but the gains are real (30p)

Data fiind o configuratie a matricii, se doreste gasirea tuturor combinatiilor castigatoare. O combinatie castigatoare este o secventa de simboluri care se afla in interiorul cadranului si care respecta urmatoarele reguli:

  • pe o linie se afla macar 3 simboluri identice; mentiune: pentru o linie in particular, se considera doar cea mai lunga secventa de simboluri identice
  • pe o diagonala se afla 3 simboluri identice (de exemplu, simbolul de pe pozitia (1, 1), (2, 2) si (3, 3) sunt identice, dar nu neaparat incepand de pe coloana 1); se considera atat diagonalele “principale”, cat si cele “secundare”, deci atat cele de forma [(1, i), (2, i + 1), (3, i + 2)], cat si cele de forma [(3, i), (2, i + 1), (1, i + 2)];

atentie: daca doua astfel de diagonale formeaza un “X”, adica se intersecteaza in simbolul din mijloc, atunci aceasta intersectie este considerata ca o singura combinatie castigatoare, in loc de doua

Cerinta este sa calculati numarul de astfel de combinatii castigatoare.

Se doreste, de asemenea, calcularea scorului obtinut de Gigel in acea configuratie. Scorul este definit ca fiind suma tuturor valorilor combinatiilor castigatoare unitare regasite in tablou. Acestea sunt valorile aferente:

  • o linie castigatoare de K simboluri identice are valoarea K, unde K este un numar arbitrar mai mare sau egal cu 3
  • o diagonala castigatoare de 3 simboluri identice are valoarea 7
  • un “X” castigator are valoarea 21

De asemenea, se mai folosesc in calculul scorului si urmatoarele bonusuri:

  • pentru oricare combinatie castigatoare din cele exemplificate mai sus, daca simbolul regasit in aceasta este 7, atunci valoarea combinatiei se dubleaza
  • daca in cadran exista cel mult 4 simboluri distincte, atunci se adauga 15 la scor; daca in cadran exista cel mult 2 simboluri distincte, atunci se adauga 100 la scor, iar aceste doua bonusuri nu se cumuleaza

Se cere calcularea scorului obtinut de Gigel.

In urma unor teste scurte, Gigel s-a vazut castigator in simulator asa ca a decis sa intre in jocul real. Convenabil, a gasit chiar un aparat identic cu simulatorul sau.

Task 3. All in. (15p)

mentiune: este preferabil ca primele doua taskuri sa fie implementate inainte de acesta

Pus in fata aparatului real, Gigel doreste sa isi noteze “castigurile”, asa incat va roaga pe voi sa il ajutati. Veti primi la inceput dimensiunile matricii, apoi matricea in sine, precum si o serie de operatii sub forma de perechi (coloana, rotatie). La final, veti afisa scorul obtinut de Gigel in configuratia finala a matricii, insumand toate scorurile obtinute in fiecare dintre stagiile intermediare.

Task 4. So close! (15p)

Gigel se intreaba, la un moment dat, ce ar putea realiza daca ar putea sa schimbe, la alegere, un simbol din matrice. Va roaga pe voi, programatorii, sa implementati aceasta functionalitate. Mai exact, el doreste sa schimbe un simbol de pe o anumita pozitie cu un alt simbol, si sa obtina scorul maxim posibil in urma acestei operatii.

Se cere sa se afiseze scorul maxim teoretic pe care l-ar fi putut castiga Gigel in aceste conditii.

Task 5. What if? ... (20p)

Dupa ce Gigel a visat cu ochii deschisi la niste castiguri fabuloase, el s-a gandit la o alta posibilitate: deoarece nu poate schimba valorile deja inscrise in aparat, isi imagineaza ca ar putea roti la alegere doua coloane, dupa propria vointa, ca sa obtina un scor maxim. Din acest motiv, va intreaba cum ar putea sa obtina un scor maxim in urma a doua rotiri cu un numar arbitrar de pozitii.

Se cere sa se calculeze castigul maxim posibil obtinut de Gigel in urma a doua rotiri.

Consideram ca ambele rotiri se fac in acelasi timp, fiind alese de noi atat coloanele pe care se vor executa, cat si numarul de pozitii rotite pe fiecare dintre ele. Asadar, se va calcula scorul unei singure configuratii.

Task 6. (Bonus) 99% of gamblers quit right before they win (20p)

Pe masura ce Gigel halucina niste rotiri spectaculoase, banii din cont i s-au terminat. Cum ultimii lui bani sunt rezervati pentru o shaorma, el incepe sa isi imagineze un joc nou, care nu mai necesita pierderi suplimentare.

Se cere implementarea unui joc nou, dupa urmatoarele reguli:

  • jocul se desfasoara in interiorul cadranului aparatului
  • scopul este de a porni din coltul stanga-sus al cadranului si de a ajunge in coltul dreapta-jos al acestuia, parcurgand drumul cu un cost minim
  • trecerea in fiecare simbol are un cost asociat, iar costul total al drumului este suma costurilor tuturor simbolurilor parcurse
  • o miscare valida inseamna o deplasare in jos, in dreapta, in stanga sau in sus
  • jucatorul nu poate iesi din cadran
  • costul fiecarei treceri este egal cu modulul diferentei dintre valoarea simbolului respectiv si valoarea simbolului initial (adica cel din stanga-sus)

Se cere calcularea costului minim al drumului. Gigel ar paria ca stie sa gaseasca acest cost mai repede ca voi, doar ca se afla in mici dificultati financiare.

Exemplu:

Raspunsul este 12. Explicatie: (7 - 5) + (5 - 5) + (7 - 5) + (5 - 1) + (5 - 1)

Formate de intrare

Fiecare task va avea datele de intrare citite de la standard input/tastatura, in felul urmator:

  • pe prima linie se afla numarul taskului, sub forma unui numar intreg de la 1 la 5
  • pe a doua linie se afla doua numere naturale N si M, separate printr-un spatiu, reprezentand numarul de linii, respectiv numarul de coloane ale matricii
  • pe urmatoarele N linii se afla cate M numere naturale, separate printr-un spatiu, reprezentand matricea
  • pentru taskul 1, dupa matrice, pe urmatoarea linie se afla 2 numere naturale, reprezentand coloana si numarul de pozitii cu care se va roti
  • pentru taskul 3, dupa matrice, pe urmatoarea linie se afla un numar natural T, reprezentand numarul de operatii de rotire, urmat de T perechi de numere naturale, separate printr-un spatiu, reprezentand coloana si numarul de pozitii cu care se va roti
  • pentru taskurile 2, 4, 5, 6 nu se vor mai citi alte date

Formate de iesire

Fiecare task va cere afisarea unor valori la standard output/consola, astfel:

  • task 1: se va afisa matricea obtinuta in urma rotirii specificare; fiecare linie va avea elementele separate de cate un spatiu, iar liniile vor fi despartite de cate un caracter newline \n
  • task 2: se vor afisa doua numere, fiecare pe cate un rand: prima valoare reprezinta numarul de combinatii castigatoare regasite in configuratie, iar a doua fiind scorul obtinut de acea configuratie
  • task 3: va fi scris un singur numar, reprezentand suma tuturor scorurilor obtinute in urma fiecarei configuratii
  • task 4: se cere un singur numar, insemnand scorul maxim total in conditiile cerintei
  • task 5: se cere un singur numar, insemnand scorul maxim total in conditiile cerintei
  • task 6: se va afisa costul celui mai scurt drum in jocul descris

Constrangeri

  • 1 ⇐ N ⇐ 1000
  • 1 ⇐ M ⇐ 500
  • 1 ⇐ T ⇐ 1000
  • 0 ⇐ matrice[i][j] ⇐ 9
  • 1 ⇐ c ⇐ M, unde c este coloana rotita
  • 0 ⇐ r ⇐ 2 ^31 - 1, unde r reprezinta numarul de pozitii cu care se va roti o coloana

Orice vector/matrice va fi alocat dinamic, folosind functiile corespunzatoare, si eliberat ulterior. In caz contrar, se vor aplica depunctari.

Pentru taskul 5, testele “mari” au fost eliminate, deoarece solutia naturala ar fi fost prea ineficienta.

Coding Style

Este foarte important, pentru orice proiect, ca codul sursă să fie ușor de citit. Astfel, de-a lungul timpului, comunitatea programatorilor a agreat un set de reguli pe care programatorii trebuie să-l respecte atunci când scriu cod. Acest set de reguli poartă numele de Coding style și include directive precum:

  • utilizarea unor nume descriptive / intuitive pentru variabile care să descrie intenția utilizării variabilei - nu folosim x, folosim num_elems
  • nu utilizăm numere magice; le ținem într-o variabilă care are un nume descriptiv
  • indentăm codul
  • etc.

În funcție de echipa / compania / proiectul la care veți lucra, coding style-ul poate diferi, în funcție de ce a fost agreat anterior, și vă veți adapta acelui stil.
În cadrul cursului de programare vom folosi regulile definite de către Cpp Core Guidelines. Acestea sunt verificate în mod automat de către checker.

Validare locală temă

Pentru a vă ajuta în dezvoltarea temei, arhiva vscode_improvements.zip conține o copie a checkerului. Pentru a instala dependențele necesare verificării pentru coding style utilizați scriptul install-linters.sh:

sudo apt-get update
sudo apt-get install -y clang clang-tidy python3 python3-pip
sudo python3 -m pip install -U pip # in caz de eroare de genul "external package manager", puteti adauga --break-system-packages
sudo python3 -m pip install cpplint

Pentru a rula checkerul local folosiți comanda:

./local.sh checker # va fi nevoie de docker deja instalat

sau

./checker/checker.py # doar verificarea output-ului testelor

sau

cd checker && ./checker.sh # checker integral, rulat local

Codul sursă este compilat folosind flagurile -Wall:

  • -Wall - compilatorul va avertiza (warn) orice operații care pot genera un comportament nedefinit

Trimitere temă

Tema va fi trimisă folosind pagina de Moodle, cursul Programarea Calculatoarelor (CB & CD), activitatea “Tema 1”.

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:

  1. Fișierele .c, .h (dacă este cazul) care conțin implementarea temei.
  2. Fișierul Makefile.
  3. Un fișier README în care descrieți rezolvarea temei.

Arhiva trebuie să fie de tipul zip.

Nu includeti fisierele checkerului in arhiva voastra.

In cazul in care testele va trec local, insa pica pe vmchecker cel mai probabil aveti o sursa de “undefined behavior in cod”. Pentru a va asigura ca scapati de aceste probleme, compilati cu flagul de compilare `-Wall` si rezolvati toate warning-urile.

Listă depunctări

Lista nu este exhaustivă.

  • O temă care nu compilează și nu a rulat pe vmchecker nu va fi luată în considerare
  • O temă care nu rezolvă cerința și trece testele prin alte mijloace nu va fi luată în considerare
  • NU acceptăm teme copiate. În cazul unei teme copiate se scade punctajul aferent temei din punctajul total.
  • [-10.0]: Matricele nu sunt alocate dinamic folosind malloc/calloc
  • [-5.0]: valgrind errors
  • [cel mult -5.0]: README insuficient detaliat
  • [-5.0]: coding style errors
  • [-100.0]: hardcodarea rezultatelor de output folosind rezultatele de referinta
programare/teme_2024/tema1_2024_cbd.txt · Last modified: 2024/11/25 14:34 by cezar.zlatea
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0