Clasa a VI-a lecția 17 - 31 ian 2019

From Algopedia
Jump to navigationJump to search

Anunț

Deși am mai menționat acest lucru, îl voi mai menționa o dată.

Zero toleranță copiatorilor la varena

Există nenumărate metode prin care puteți trimite surse care nu sînt ale voastre la varena. Indiferent că este vorba de voi, sau de orice alt concurent, dacă aflu că cineva trimite surse copiate la varena îi voi anula contul. Dacă acel cineva este unul dintre voi, el sau ea își va pierde calificarea la cursurile IQ Academy.

Unul din abuzurile frecvente, din cauza căruia am anulat multe conturi, este următorul: cineva descarcă testele, apoi scrie un program care răspunde fix acelor valori de intrare, dînd la ieșire valorile cerute, copiate chiar din teste. Acea sursă va lua 100p, permițînd accesul la toate celelalte surse trimise. Moment în care copiatorul descarcă o sursa a altui concurent, o modifică și o trimite. Această a doua trimitere poate părea o sursa în regulă.

Îmi este greu să detectez astfel de abuzuri și nici nu vreau să îmi transform viața în poliția site-ului varena. Drept care, atunci cînd rareori dau peste o sursă clar copiată pedeapsa trebuie să fie pe măsura greutății descoperirii ei: anularea contului.

Tema - rezolvări

Problema dvorak

Comentarii generale

  1. Felicitări celor ce au reușit o soluție foarte bună: Nicola, Rebengiuc, Ilie, Nicu.
  2. Unii din voi mi-au trimis soluția trimisă în concurs. Care este scrisă în grabă și fără mare grijă la perfecțiune, pe principiul "merge și așa". Aceasta este lene, la temă mă aștept la soluții perfecționiste, la concurs nu. Aveți respectul de a nu mă pune să corectez surse groaznice, prima idee care v-a venit sub presiunea timpului! Ne supărăm!
  3. Unii din voi ați greșit condiția de oprire la căutarea șirului în parolă, un < în loc de <=. Aveți noroc că testele nu testează limita, altfel pierdeați puncte.
  4. Mulți dintre voi nu v-ați oprit cînd ați găsit prima apariție a șirului în parolă, codul fiind neoptim.
  5. Unii din voi au declarat parola și șirul cu un element în plus din lenea de a ajusta indicii la intrare. Vă rog să nu faceți așa ceva.
  6. Mulți dintre voi ați implementat operațiunea de tip 1 astfel:
        s--;
        d--;//ajustez pt ca vectorul incepe de la 0
        for(j=s;j<=d;j++)
          p[j]=v[p[j]-'a'];

Nu este greșit, dar de ce să pierdem timpul ajustînd variabile cînd oricum avem o buclă? Puteam scrie mai simplu:

        for(j=s-1;j<d;j++)
          p[j]=v[p[j]-'a'];
  1. Unii dintre voi nu au știut cum să apeleze v[i], unde i este a cîta literă în alfabet este 'a'. Ei au scris niște bucle ciudate, la modul:
      char alfa[26]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
      ...
          for(ii=s;ii<=d;ii++){
            c=p[ii];
            jj=0;
            while(c!=alfa[jj])
              jj++;
            p[ii]=dv[jj];
          }

    Cu greu o ciudățenie mai mare! Dragilor, caracterele au coduri consecutive! Dacă ch este o literă mică, atunci indicele ei în alfabet este ch - 'a'! Drept care codul de mai sus se scrie, ușor:

          for(ii=s;ii<=d;ii++)
            p[ii]=dv[p[ii]-'a'];
  2. Sînt uimit de faptul că majoritatea dintre voi nu știu să scrie căutări, după atîtea repetiții la cursuri și la teme, cu căutări în fel și chip, inclusiv în matrice.
  3. Nimeni dintre cei ce au dat o rezolvare corectă la căutare nu s-a prins că puteți evita o repetiție, la căutare, o inițializare cu zero atît în buclă, cît și în afara buclei.
  4. Rușine celor ce încă nu știu să scrie o căutare (scriu cu stegulețe în bucla de bază sau numără egalități de caractere): Benescu, Grecu, Asgari, Stancu. Pe Calotă și Teodorescu îi iertăm (deocamdată) căci sînt mai noi.
  5. Avertismente celor ce nu au trimis nici o soluție la această problemă: toată lumea a trimis surse, bravo!

Comentarii individuale

Grupa de dimineață

  • Aizic (100p): Programul este rezonabil, dar cu ceva probleme la căutarea șirului în parolă:
    • Instrucțiunea for(r=0;r<n-n1;r++) are limita greșită, trebuia să pui semnul mai mic sau egal.
    • La aceeași instrucțiune, folosești un for pentru căutare. Este neoptim, deoarece nu te vei opri imediat ce ai găsit o apariție.
    • Folosești un steguleț, deși știi bine că la căutare nu folosim stegulețe

Concluzie: revizitează căutarea și studiază soluția de mai jos.

  • Badea (100p): Program aproape perfect. Căutarea se oprește cu o poziție mai devreme, condiția while(i<n-k && j<k) trebuia să fie while(i<=n-k && j<k)
  • Benescu (100p): Program de mediocri. Căutare groaznică, cu steguleț în bucla de bază. Revizitează lecția de căutare. Înțeleg de ce ai declarat parola[] și sir[] de 501 elemente: din lene, pentru a nu scădea 1 din valorile de la intrare. Asta nu înseamnă că și aprob. Dar nu înțeleg de ce ai declarat dvorak[] de 27 de elemente? În fapt îți complică codul, trebuie să adaugi 1 la fiecare conversie! Nu mai folosi indici de la 1 fără motiv solid!
  • Burac (100p): Program bun, căutarea este jale:
    • folosești steguleț inutil în bucla exterioară (puteai să testezi direct că in < p în bucla exterioară.
    • Faci o aiureală, testînd primul caracter separat. De ce?
    • Limita q < n este neoptimă, trebuia q + p <= n

Alte observații:

        x = parola[p] - ( 'a' - 1 ) - 1;
        parola[p] = permutarea[x];

Se scria mult mai simplu:

parola[p] = permutarea[parola[p] - 'a'];

Dacă te-a speriat acel avertisment că indicele este caracter puteai să faci o conversie explicită:

parola[p] = permutarea[(int)parola[p] - 'a'];

Nu complica codul te rog.

  • Calotă (100p) : Mi-ai trimis sursa de la concurs, o sursă neglijentă cu o căutare de subșir în șir groaznică și multe alte bube. De exemplu, codul următor va depăși cele 500 de caractere, deoarece citești și '\n' tot în vector:
   while ( par[n] != '\n' ){
      n++;
      par[n] = fgetc ( fin );
   }

Folosești coduri ASCII în program! Nu 97 ci 'a'! Te rog să revizitezi căutarea, unui subșir în șir, este atît de aiurea că nu are sens să corectez ceva la ea. Nu afișa rezultate în buclă, atunci cînd poți să le afișezi la final.

  • Chivu (100p): Un program aproape bun. Dacă nu foloseai stegulețul gasit ci mutai exact testul în while, totul ar fi fost perfect: while(j<=n2-nr && k<nr). Păcat... Atenție la dublura variabilelor j și nr, ele merg în paralel în bucla de citire a șirului, nu are rost.
  • Cojocariu (100p): Mi-ai trimis sursa din concurs. O sursă OK, cu excepția căutării, care folosește un steguleț mascat, j, care este și indicele de buclă. Revizitează căutarea unui șir în șir, sau vezi soluția de mai jos.
  • Coman (100p): o rezolvare OK, dar căutarea are limitele greșite (comentariul 3) și folosește steguleț. Neoptimală deoarece nu se oprește cînd găsește șirul în parolă.
  • Dragomir (0p): greșeli de elev începător în informatică:
  • permutarea este un vector indexat de la 1, dar dimensionat de 26 în loc de 27
  • la fel și șirul de căutat
  • folosești coduri ASCII în program. Precum am vorbit anul trecut, nu 97 ci 'a' (în cazul tău + 'a' - 1)

Este păcat căci programul pare să funcționeze, după ce am corectat limitele vectorilor la 27, respectiv 501 elemente. Căutarea este neoptimală deoarece nu se oprește la prima apariție și folosește stegulețe.

  • Grecu (100p): Am ignorat ultima sursă pe care ai trimis-o la arhivă; conține funcții pe șiruri pe care evident nu le înțelegi, căci le folosești greșit. Voi discuta despre sursa de la temă, aceeași cu cea din concurs. Programul tău arată că știi să mînuiești șiruri de caractere, ceea ce e bine. Ce este rău, e faptul că nu știi să faci o căutare. Programul tău este împotriva a ceea ce învățăm de peste un an de zile, folosești stegulețe, numeri apariții de egalități, nu te oprești la găsirea șirului în parolă. Este un cod de începător, mediocru, OK pentru concurs, dar nu pentru temă. Urît.
  • Hossu (100p): în afară de faptul că soluția ta seamănă cu a lui Iordache, cu întocmai aceleași greșeli, codul este rezonabil, te descurci cu citirea caracterelor și căutarea unui șir pe o poziție. Ți se aplică comentariile 3 și 4 de mai sus. Faci și o ciudățenie mare, folosești un vector de caractere în care a[i]=='a'+i, deci nu ai nevoie de vector! Mai exact, în loc să scrii:
      for (j = si - 1; j < di; j++) {
        k = 0;
        while (a[k] != p[j] && k < 26)
          k++;
        p[j] = v[k];
      }

puteai scrie mult mai simplu:

      for (j = si - 1; j < di; j++)
        p[j] = v[k - 'a'];
  • Iordache (100p): maestre, nu pot să citesc cod în care variabilele se numesc i, i2, i3, i4 și i5. În fapt, nimeni nu poate! Te rog să le denumești altfel și, mai ales, ar fi minunat să scrii programe care nu folosesc cinci indici diferiți! Ai trimis sursa de la concurs, o sursă complet necizelată. Ar trebui să nici nu mă uit pe ea. Citește te rog comentariile lui Hossu, aveți greșeli similare. Ai grijă că el a te-a surclasat, a știut să nu testeze aiurea dacă operația este doi, ci a folosit o proprietate incredibilă a instrucțiunii if, pe nume else!
  • Mocanu (100p): un program destul de bun. Ți se aplică și ție comentariile 3 și 4. Revezi căutarea și neapărat înțelege soluția de mai jos, fără stegulețe și care se oprește la prima apariție a șirului în parolă.
  • Mușat (100p): se vede că te descurci cu șiruri de caractere. Asta e partea bună. Codul este destul de ordonat. Problema este la căutare. Ți se aplică comentariul 4, folosești steguleț și nu te oprești la prima apariție. Ai făcut o modificare a căutării care nu ajută cu nimic. Și, cel mai grav, greșeală de începător, modifici variabila de ciclu, i, în interiorul buclei for.
  • Nicola (100p): Felicitări, un program aproape perfect! Ai doar o mică redundanță, cînd verifici ca lungimea șirului de căutat să fie mai mică sau egală cu a parolei. Nu este necesar, celălalt caz acoperă și acest caz, deoarece dacă lungimea este prea mare nu se va intra în while. Felicitări, aș fi vrut să văd mai multe programe ca al tău.
  • Petcu (p): Programul este rezonabil, pentru concurs. Nu și pentru temă. Vă las ca temă aceleași probleme nu pentru ca voi să trimiteți fericiți aceeași sursă de la concurs și să scăpați ieftin, ci pentru ca voi să corectați programul imperfect din concurs. Deci, este ca și cum nu ți-ai făcut tema. Problema cea mai mare a acestui program este căutarea. Ai greșit condîția de oprire la comparație, este suboptimal deoarece nu se oprește cînd găsește o apariție a șirului în parolă, și folosește stegulețe inutile Ți se aplică comentariile 2, 3 și 4). Mai departe, codul acesta dă depășire, deoarece vei citi un caracter în plus în vector, '\n':
    i = 0;
    parola[i] = fgetc( fin );
    while( parola[i] != '\n' ) {
      i++;
      parola[i] = fgetc( fin );
    }

La fel și la citirea șirului de căutat. Greșeli de începătoare.

  • Rebengiuc (100p): un program perfect, bravo! Ești printre puținii care nu a greșit la căutare, felicitări! Atenție! Nu lăsa printf de debug în sursă! Foarte periculos, poți primi TLE.
  • Rughiniș (100p): programul tău este rezonabil. Felul în care îți denumești variabilele este neglijent. Faci codul greu de citit și înțeles, ceea ce îmi îngreuiază corectura, iar ție îți crește timpul de rezolvare. Căutarea este aproximativ bună, nu folosești stegulețe și te oprești la prima apariție. Dar adaugi o modificare care nu are rost, cauți primul caracter din șir. Același lucru îl face și bucla a doua. Ți se aplică comentariul 7, ai rezolvat punctul 1 în cel mai complicat fel cu putință.
  • Stoian (85p): Codul este rezonabil și relativ ordonat. Ți se aplică comentariul 7, ai rezolvat punctul 1 în cel mai complicat fel cu putință. La punctul 2, căutarea folosește steguleț în bucla exterioară. Folosește două variabile k și l care au mereu aceeași valoare. Mai multă atenție la eficiență și la evitarea stegulețelor, ești pe drumul cel bun!
  • Ștefănescu (100p): sursa pe care ai trimis-o în concurs arată o voință mare de a lua puncte. Respect acest lucru. Comentarii la sursa de la temă: felicitări pentru 100p. Se vede că nu ai experiență în lucrul cu caractere, te rog să revezi lecția de anul trecut! Pentru citirea caracterelor folosim fgetc( fin ), fscanf este lent și periculos. De ce ai declarat trans[27] și nu de 26 de elemente? Pentru ca apoi, mai tîrziu în program să poți scrie v[j] = trans[v[j]-'a'+1];? :-) Nu era mai simplu să ai 26 de elemente începînd de la zero și să scrii v[j] = trans[v[j]-'a'];? Ecaterina, vectorii la IQ Academy încep de la zero. Ține minte te rog, să nu se mai repete. Trebuie să ai un motiv extrem, dar extrem de serios, să începi un vector de la unu. La punctul doi, nu este nevoie să îl faci pe sir[] zero, el va fi suprascris cu caracterele citite la intrare. Căutarea este complet dezordonată, cu stegulețe și alte minuni. Te rog să revizitezi lecția de căutare și să te uiți cu mare atenție la rezolvarea de mai jos. La IQ Academy nu folosim stegulețe la căutare!
  • Togan (100p): Un program rezonabil, dar neglijent. Ca orice program scris în grabă, la concurs. Pe care apoi mi-l trimiți mie la temă ca să scapi repede de muncă. Togan, dacă nu vrei să muncești, spune-mi și se rezolvă! Nu-mi da mie să corectez prostii pentru că ție ți-e lene să-ți pui creierul la contribuție. Să vedem. Vectori care încep de la 1, de ce? Dacă nu ai un motiv serios ne supărăm! În căutare folosești un steguleț mascat, contorul j. Căutarea nu se face cu stegulețe! Vezi codul de mai jos. De asemenea, niciodată, dar niciodată nu ai voie să modifici variabila de ciclu într-o instrucțiune for! Togan, ne supărăm rău! Atenție, la final ai un fprintf de debug, chiar în fișierul out! Îți place să trăiești periculos?
  • Voicu (100p): un program bun, dar cu neglijențe. Probabil pentru că odată ce ai luat 100p la concurs nu te-ai mai obosit să-l faci perfect, pentru temă. Mi l-ai trimis mie așa. Să vedem:
    • declari int v[27], dar folosești doar 26 de elemente. Năravul piere greu, nu? :)
    • simpatică matricea predeclarată de caractere pentru o afișare uniformă :)
    • așa scrii citirea? Îți place să scrii în plus aiurea?
    for(i=0;i<26;i++) {
        c=fgetc(fin);
        v[i]=c;
    }

nu era mai simplu așa?

    for(i=0;i<26;i++)
        v[i]=fgetc(fin);
    • nu folosi fscanf pentru a citi șiruri de caractere. Este periculos, de aceea nu v-am învățat. Pe de altă parte, permutarea de 26 de cifre nu ai citit-o cu fscanf. Hotărăște-te!
    • nu-mi vine să cred că ai scris o căutare cu stegulețe. De la tine nu mă așteptam.
    • limita finală a începutului șirului de căutat este greșită, vezi comentariul general 3.

Grupa de după-amiază

  • Asgari (100p): Armin, nu mă așteptam să îmi trimiți un program cu greșeli de bază, de începător, cu declarații de vectori cu elemente în plus și o căutare cu două, nu doar un steguleț. Desigur că mi-ai trimis sursa din concurs, scrisă în grabă. Probabil nu merit să mai muncești înca 30 de minute acasă pentru a transforma sursa de concurs în una perfectă, așa cum mi-aș dori de la tine. Fără comentarii :(
  • Cadîr (95p): Programul tău este ordonat, dimensionează corect vectorii și citește frumos șirurile de caractere. Rezolvarea la punctul 1 este foarte bună. La linia 47 îl setezi pe i la zero de două ori. Să fii sigur :) Căutarea este rezonabilă, dar neglijentă, face multe teste și, cel mai rău, folosește un steguleț pentru bucla exterioară.
  • Dobre (95p): un program destul de muncitoresc. Se vede că stăpînești bine codul, știi să citești șiruri de caractere, dimensionezi bine vectorii. Din păcate te-a fentat punctul unu, lucrul cu caractere. Vezi comentariul 7, e o greșeală de gîgă. Iar căutarea de la punctul doi folosește un steguleț ascuns, contorul x.Căutările se scriu fără stegulețe!
  • Fares (100p): Bravo, un program destul de ordonat. Ca fapt divers, numărul de litere mici din codul ASCII este 26, nu 28 :) Singura obiecție la programul tău este căutarea. Tu maschezi într-o funcție o nestructurare. Instrucțiunea return în mijlocul unei funcții este echivalentul unui break care duce la finalul funcției. Fie nu știi cu adevărat funcții, caz în care ar fi bine să te abții din a le folosi, fie înțelegi că ai un program nestructurat și nu îți pasă? Cum stau lucrurile?
  • Ilie (100p): Un program perfect! Bravo! Nu numai l-ai scris perfect, dar ai făcut asta în timpul concursului. Ești unul dintre puținii cu o soluție perfectă.
  • Ipate (100p): un program solid, ordonat și curat. Din păcate am obiecții, unele îngrijorătoare:
    • Ai declarat vectorii de parolă și șir de 500 de caractere, dar tu citești în ei și caracterul '\n', deci vei depăși vectorii. Grav, atenție la calcule.
    • Căutarea nu se face cu stegulețe. Funcționează, e corectă, dar nu e optimă.

În rest totul este bine, bravo. Mi-aș fi dorit de la tine să scrii o căutare frumoasă.

  • Marcu (100p): Ilinca: felicitări pentru cele 100p luate în concurs. Însă nu poți să îmi trimiți aceeași sursă, nepieptănată, și la temă! Ce e cu toate avertismentele alea de compilare? Îmi dai un astfel de program, înseamnă că nu îți pasă de mine, orice merge. Sursa ta nu respectă regulile cercului nostru. Iată:
    • Folosești vectori de la indicele 1, în loc de 0
    • Folosești instrucțiunea for acolo unde trebuia să folosești while.
    • Ai avertismente de compilare care nu sînt OK.

Ilinca, acestea sunt lucruri de bază, stabilite acum mai mult de un an. La IQ Academy nu dăm cu for-ul, căci nu avem nevoie de IQ pentru asta, nu? Ne supărăm rău de tot. Pe lîngă asta, mai ai alte probleme:

    • Declari vectorii de 501 elemente, dar citești în ei și '\n', deci vei depăși vectorii. Atenție la limite!
    • Folosești stegulețe pentru căutare. La IQ Academy nu folosim stegulețe în căutări, am vobit despre asta de nenumărate ori. Revezi lecția de căutare și vezi soluția de mai jos, te rog.
  • Nicu (100p): Un program foarte bun, bravo! Mici încîlceli la căutare, dar este corectă, fără stegulețe aiurea. Ai dimensionat vectorii cu un element în plus, dar te iertăm, avînd în vedere cît de rare au fost sursele bune. Felicitări!
  • Stancu (100p): David, mă bucur că ai dus programul pînă la capăt și că ai luat 100p din prima, bravo. Dacă îți pui mintea, poți orice. Ca obiecții, ai folosit vectorii de la 1 și nu de la 0, iar căutarea nu are nici o legătură cu ceea ce am învățat noi la IQ Academy, este foarte urîtă. Măcar nu ai folosit două stegulețe, ca Armin :)
  • Tatomir (100p): o rezolvare rezonabilă, dar de la tine mă aștept la mai mult decît rezonabil, nu? De ce ai folosit vectori de la 1 și nu de la 0? Căutarea folosește un steguleț, știi că nu facem așa ceva. Iar adăugarea personală, acea căutare a primului caracter din șir în parolă, nu are nici un rost. Următorul while acoperă acel caz, deci nu faci decît să încetinești căutarea.
  • Teodorescu (100p): un program bun, se vede că progresezi, bravo! Ai citit bine caracterele și ai rezolvat perfect punctul unu. La punctul doi mai trebuie perfecționată căutarea. Ai următoarele probleme:
    • Folosești o buclă for, dar modifici variabila de ciclu. Trebuia să folosești while.
    • Folosești un steguleț. Căutarea se face fără stegulețe.
    • Nu te oprești atunci cînd ai găsit cuvîntul în parolă.

Te rog să te uiți pe lecțiile din urmă, peste tot unde avem căutări, pentru a le învăța corect.

Problema tetris

Comentarii generale

  • Avertismente celor ce nu au trimis nici o soluție la această problemă: Aizic, Coman, Iordache, Cadîr.

Rezolvări aici [1]

Lecție

<html5media height="720" width="1280">https://www.algopedia.ro/video/2018-2019/2019-01-31-clasa-6-lectie-info-17-720p.mp4</html5media>

Discuție probleme din tema 15.

Problema bile 2

Urmează comentariile lui Mihai la soluțiile voastre.

Comentarii generale

  • Felicitări celor care au obținut punctaj maxim și cu o rezolvare optimă: Aizic Albert, Badea Lucian Andrei, Burac Alexandru, Calotă Andrei, Coman Mihai, Iordache Rareș Mihai, Ipate Elisa, Mocanu Mihai, Mușat Tudor și Voicu Tudor.
  • Țin să atrag atenția că o parte dintre voi ați pierdut puncte din neatenție. Ne apropiem de concurs, trebuie să fiți responsabili. Respectați problemele și nu le tratați cu superficialitate. Fiți atenți la ce iterați și când o faceți. Vedeți observațiile individuale pentru a înțelege mai bine.
  • Marea majoritate a soluțiilor care au punctat maxim sunt cu bucle while imbricate. Puteați face simularea într-o singură buclă while, nu era nevoie să mai imbricați una. Soluția cu două bucle tinde să fie mai complexă, iar în cazul unei implementări greșite poate chiar mări complexitatea soluției. Urmăriți soluția dată mai jos pentru a înțelege ce puteți îmbunătăți.
  • Avertismente celor ce nu au trimis nici o soluție la această problemă: Grecu.

Comentarii individuale

Am scris doar pentru cei care nu au obținut punctajul maxim și/sau am simțit nevoia să fac observații. Ceilalți, vreau să urmăriți rezolvările pentru a vă îmbunătăți programele voastre.

Grupa de dimineață

  • Chivu Andreea (90): Soluția este corectă, însă ușor mai complicată în urma utilizării condițiilor if imbricate. Ajungi să verifici în 2 locuri dacă e nevoie să scrii "I". Vezi mai jos o posibilă rezolvare ce te scapă de această dublă verificare.
  • Dragomir Denisa Elena (76): Atenție! Soluția ta nu verifică și cazul în care este imposibil rezultatul. În acele cazuri în care se află în imposibilitate, algoritmul tău intră în bucla și iterează "I" până ajungi la capătul vectorului. Abordarea ta doar testează dacă poate scrie "IO", "I" sau "O".
  • Rebengiuc Mircea (18): "Atenție la indici! Parcurgi vectorul de caractere de la 0 la capăt, inclusiv, în momentul în care faci scrierea în fișier. Astfel, mergi pe o poziție a vectorului care nu conține nimic și duce la apariția unui caracter în plus la sfârșitul șirului afișat, NULL. Modificarea este următoarea:
     //din
for( i = 0 ; i <= ncmd ; i++ )
    
    //în 
for( i = 0 ; i < ncmd ; i++ )
  • Rughinis Remus (80): În cazul tău, eroarea "Killed by Signal 6 (SIGABRT)" se referă la faptul că ieși din vector. Dacă ai pornit contorul de la 1, atunci trebuie să mergi la n+1 poziții. Astfel, vectorii tăi trebuie sa aibe 2001 poziții.
     //din
int a[2000],b[2000];
    
    //în 
int a[2001],b[2001];
  • Ștefănescu Ecaterina (100): Soluția oferă răspunsul corect, însă codul parcurge foarte multe condiții, mult prea multe decât este cazul. Să ne amintim că trebuie să găsim o soluție care să aibe cât mai puțin cod și să fie cât mai optimă. Vezi rezolvarea sugerată de mai jos.

Grupa de după-amiază

  • Nicu Alexandru (95): Soluția ta este corectă, însă ai foarte multe condiții if și locuri în care modific stegulețul "ok". Vezi mai jos o posibilă rezolvare ce te scapă de acestea.
  • Stancu Andrei (0): Ai încercat la Arhiva de probleme o abordare la care ai luat 20 de puncte. Algoritmul are o problemă de logică în felul în care parcurgi indicii în vectori. Vezi mai jos o posibilă rezolvare.
  • Teodorescu Nicolas (16): Apreciez că te-ai luptat cu problema. Am văzut că ai reușit să obții punctaj maxim în cele din urmă (după 6 submisii :) ) .


Problema ouă

Comentarii generale

  • Felicitări celor ce au reușit o soluție foarte bună: Benescu, Burac, Chivu, Grecu, Hossu, Rebengiuc, Ștefănescu, Asgari, Dobre, Fares, Ilie, Ipate, Marcu, Nicu.
  • Notă specială pentru o soluție deosebită lui Tatomir.
  • Unii din voi ratați testul 3 deoarece faceți mai întîi avansul iepurilor și abia apoi testați ouăle. De aceea pierdeți ouăle aflate chiar pe margine, în punctele de pornire ale iepurilor.
  • Avertismente celor ce nu au trimis nici o soluție la această problemă: Cojocariu, Coman, Iordache, Stoian, Cadîr, Stancu.

Comentarii individuale

Grupa de dimineață

  • Aizic (90p): bravo, codul arată foarte bine! Sper că este complet al tău. Nu ai folosit bordare, de ce? Declari vectorii de direcție de cinci elemente, în loc de patru, de ce? Direcția ta avansează modulo 4 (corect), dar în sens negativ. Era mai simplu în sens pozitiv. Pici testul 3 deoarece tu faci intîi avansul iepurașilor și abia apoi verifici dacă are ou. Dacă ai ouă pe pozițiile inițiale le vei pierde.
  • Badea (10p): codul tău aproape mergea, te-ai înecat la mal. Ești sigur că te-ai străduit să-l repari? Cam ciudat că nu ai reușit. Ai avut trei greșeli de neatenție: ai inițializat t[i] cu 1 în loc de 0, ai inițializat cnt cu 0 în afara buclei while, trebuia să fie prima instrucțiune în interior și ai actualizat coșurile cu ouă după ce setai oul în matrice pe zero, deci nu adunai nimic la coșuri. În special ultima greșeală este atît de evidentă. Ciudat că nu te-ai prins.
  • Benescu (100p): cod bun, bravo! Te-ai chinuit ceva să "înghesui" trei valori în una, în vectorul de iepuri :-) Drăguță idee și eficientă, dar cred că ar fi fost mai clar codul si mai ușor să ai trei vectori. Mai ales că valoarea coșului nu ai adăugat-o la acea valoare combinată. Fii consecvent!
  • Burac (100p): program foarte bun, bravo. Ai mici încîlceli de logică: în loc să testezi dacă iepurele dispare imediat după ce l-ai avansat, o faci abia în bucla următoare. De aceea ai nevoie să ajustezi numărul de minute cu unu, la final.
  • Calotă (38p) : codul tău aproape mergea, te-ai înecat la mal. Motivul principal pentru care îți dă TLE este faptul că tu continui să scazi din -1 atunci cînd un iepure iese în afara pajiștei, pentru a nu îl scădea de două ori din numărul de iepuri curent. Problema este că dacă un al doilea iepure iese în același loc de pe pajiște nu vei găsi -1 acolo, ci ceva mai mic, drept care nu îl vei considera ca dispărut. Numărul iepurilor de pe pajiște nu va mai scădea la zero niciodată și, deci, buclă infinită :-). Pentru a repara problema trebuie să nu mai scazi din punctul de ieșire și să muți acel if mai sus, în interiorul if-ului de deasupra lui. Atenție, direcția ta avansează modulo 4 (corect), dar în sens negativ. Era mai simplu în sens pozitiv.
  • Chivu (100p): cod foarte bun, bravo! Cîteva încîlceli: iep[i][3], adică numărul de ouă per iepure, nu se cere, este nenecesar. Probabil e o rămășiță dintr-o versiune anterioară :-) Direcția, așa cum v-am povestit și la curs, putea avansa simplu și drăguț: dir = (dir + 3) % 4. Tu ai scris un cod cu multe teste.
  • Cojocariu (0p): nimic? Chiar așa?
  • Coman (0p): nimic?
  • Dragomir (0p): programul este destul de greu pentru clasa a 5a și înțeleg. Aș vrea să comentez la greșelile grave chiar și la clasa a 5a:
    • linia de citire fscanf(fin, "%d %d", &l1, &n); conține spațiu între cei doi %d. Nu e OK, am discutat despre asta acum un an. Faci asta la toate citirile.
    • linia de citire fscanf(fin, "%d %d", &l, &c, &val); are doar doi %d dar citește trei variabile. Mai mult, ai și avertisment de compilare în acest sens. Greșeală de începător.
    • reprezinți pajiștea ca o matrice de 2000x2000 elemente. De ce? Problema spune că este maxim 50x50 elemente.

Restul problemelor sînt mai puțin grave la clasa a 5a și totuși îngrijorătoare: muți iepurii imediat ce i-ai citit. Nu putem face acest lucru, nu corespunde enunțului, iepurii sar toți o dată. La lecție am avut o discuție amplă despre cum implementăm, cum memorăm iepurii, etc. În continuare nu înțelegi bordare și vectori de direcție.

  • Grecu (90p): Program excepțional. Singura problemă, probabil motivul pentru care ratezi un test cu TLE, faci bordare dar nu ai declarat matricea cu două elemente în plus. Atenție la neatenție!
  • Hossu (100p): cod foarte bun, bravo!
  • Iordache (0p): nimic?
  • Mocanu (40p): folosești bordare, dar apoi te întrebi dacă iepurii sînt pe margine, ceea ce anulează bordarea. Declari vectorii de direcție de cinci elemente, în loc de patru, de ce? Este uimitor cîte puncte ai putut lua fără să ștergi ouăle de pe tablă. Foarte bine că ai corectat programul final, trimis la arhivă, bravo!
  • Mușat (85p): nu folosești nici bordare, nici vectori de direcție. Ignori nu numai lecțiile ci și instrucțiunile pentru teme, la care am stat o oră! Mușat, scopul acestor lecții și teme este exact să învățăm vectori de direcție! Tu pare că nu vrei să le înveți. Poate că nu ar trebui să te afli printre noi. Ți-aș fi corectat programul și ți-aș fi spus unde e greșeala, dar dacă tu nu respecți cerințele, nici eu nu-ți dau comentarii.
  • Nicola (80p): felicitări că te-ai apucat să recuperezi problemele din urmă, bravo! Program bun, aproape perfect. Tot ce mai aveai de făcut era să testezi în bucla for, ca prim test, dacă iepurele este afară și doar atunci să îl prelucrezi. Altfel vei continua să muți iepurii în afara matricei. Felul cum schimbi direcția este complicat. Puteai să o incrementezi modulo patru, cu condiția să aranjezi direcțiile în ordinea corectă în vectorii de direcție.
  • Petcu (100p): mă bucur că rezolvi probleme în avans. Dar cînd faci asta uneori nu vei găsi soluția optimă, deoarece nu aveai cunoștințele necesare. În astfel de situații trebuie să refaci tema. Tu nu ai refăcut-o, drept care nu folosești bordare, exact scopul acestei teme. În afară de asta, programul este rezonabil. Observații: Direcția ta avansează modulo 4 (corect), dar în sens negativ. Era mai simplu în sens pozitiv. În loc să cauți la fiecare iterație dacă mai există iepuri pe pajiște, puteai să ții numărul de iepuri pe pajiște și să îl ajustezi la ieșirile iepurilor. Alternativ, puteai să numeri iepurii pe pajiște în bucla principală de avans a iepurilor. În ambele variante scăpai de steguleț.
  • Rebengiuc (100p): Program perfect, bravo! Ordonat, cu comentarii folositoare și respectă toate cerințele și indicațiile de la oră.
  • Rughiniș (0p): Programul tău nu are nimic greșit, principial. Tot ce aveai de făcut era să îl depanezi. De ce nu ai făcut asta, nu știu. Greșelile pe care le-am corectat pentru a lua 100p:
    • Inițializarea timpului cu 0 nu cu 2 (asta sună a programare aproximativă)
    • Inițializarea direcțiilor iepurilor (valori inițiale greșite)
    • Schimbul de direcție în sens invers (dreapta, nu stînga cum făceai tu)
    • Adunat diferențele de linie la linie și de coloană la coloană (nu pe dos, cum făceai tu)
  • Stoian (0p): Nimic? Ai făcut toate temele mai puțin ouă. E așa o problemă urîtă?
  • Ștefănescu (90p): un program foarte bun, care respectă toate cerințele. Bravo! Pierzi testul 3 deoarece faci mai întîi avansul iepurilor și abia apoi testezi ouăle. De aceea pierzi ouăle aflate chiar pe margine.
  • Togan (90p): denumirile vectorilor sînt foarte neclare. De ce nu le spui sugestiv, lin, col, dir, cos, etc? Programul devine artificial greu de urmărit din cauza asta. Nu folosești bordare. Aceasta era tema lecției, bordarea și vectorii de direcție. Codul este neglijent scris și cu repetiții. Tratezi în bucla for lucruri care se întîmplă o singură dată, și trebuiau făcute la început. Pentru asta folosești un steguleț st. Foarte, foarte urît. Iar atunci cînd st este 0 testezi inutil dacă coordonatele nu sînt în afara tablei. De ce faci asta? Pentru că ai făcut copy/paste din ramura else. Te-ai grăbit, ți-a fost lene, tu știi. Togan, dacă vrei să rămîi printre noi trebuie să urmezi regulile. Altfel poți să nu mai vii.
  • Voicu (90p): nu prea înțeleg ce s-a întîmplat aici. Ai trimis cînd la temă, cînd la arhivă. Deși aveai 100p la o soluție mai veche, ai reușit cumva să iei 90p la temă. Ai trimis o sursă cu extensie .cpp deși ea e .c Matricea b[] este inutilă, nu? Iepurii sînt numerotați de la 1, nu știu de ce. Codul este OK, dar încîlcit, parțial și din cauză că folosești două matrice. Scoți ouăle de pe tablă abia la finalul buclei, într-o altă buclă, de ce nu în timpul avansului iepurilor? Declari împreună matrice și variabile simple, în aceeași declarație int a[MAX+2][MAX+2],n;. Motivul pentru care ratezi ultimul test este tocmai faptul că te încurci în matricea b. Tu setezi b[][] la zero în a doua buclă for, inclusiv pentru iepurii care au coordonate invalide. Asta, combinat cu faptul că matricea b[][] e declarată de 51 de elemente în loc de 52 face ca o scriere în b[][] să scrie de fapt în n, făcîndu-l zero, drept care maximul nu se mai calculează. Voicu, programul tău nu este unul rău, dar este extrem de dezordonat și încîlcit. Faptul ca știi și folosești struct este hilar, cîtă vreme nu știi lucruri de bază.

Grupa de după-amiază

  • Asgari (100p): Program frumos și ordonat, bravo! Ca observații, de ce vectorul de iepuri are 101 elemente? N-ai nevoie de 'gata', puteai testa direct dacă cnt1 este egal cu n.
  • Cadîr (0p): nimic? De ce?
  • Dobre (95p): Un program bun și solid, bravo! Ca observații, direcția se putea ajusta modulo patru, matematic, așa cum am vorbit la ore. Tu ai scris un mare switch, cînd puteai rezolva eficient într-o singură linie. Puteai ajusta variabila 'gata' în primul for, nu aveai nevoie de al doilea.
  • Fares (100p): Bravo, un program destul de ordonat, care respectă toate cerințele! Ca observ ații, în declarații, linia int mat[52][2502], dir[101], l[101], c[101], sol[101];, de ce vectorii de iepuri au 101 elemente și de ce matricea are 2502 elemente? N-are noimă, atenție la limite! Te rog nu declara vectori sau alte variabile în mijlocul programului, așa cum ai declarat vectorii de direcție.
  • Ilie (100p): Un program foarte bun și ordonat, solid, care respectă cerințele. Ai făcut și o optimizare interesantă, ai compactat iepurii atunci cînd unul din ei iese din pajiște, frumos!
  • Ipate (100p): O soluție bună, ordonată, care respectă cerințele, bravo! Mulțumesc pentru comentarii. Interesant că te-ai gîndit să optimizezi întregii. Cum de nu ai declarat vectorii de direcție de tip char, în acest caz? :-)
  • Marcu (90p): Program foarte bun și ordonat, care respectă cerințele. Ai ratat testul 3 deoarece avansezi mai întîi iepurii și abia apoi testezi ouăle. Pierzi, astfel, ouăle de la marginea tablei, care se află chiar sub iepuri la pornire.
  • Nicu (90p): Program foarte bun și ordonat, care respectă cerințele. De ce ai declarat vectorii de iepuri de 101 elemente? Atenție la limite!
  • Stancu (0p): nimic? Chiar așa grea a fost?
  • Tatomir (100p): să înțeleg că ai învățat de curînd despre cozi? Și acum cauți probleme unde să le folosești? Ei bine, aici nu era o astfel de problemă :-) Văd că ai trimis cam aceeași rezolvare de mai demult. Este interesantă, ea fiind relativ eficientă, deoarece nu tratează iepurii ieșiți din pajiște. Problema este că nu numai că ai o coadă foarte mare, dar, așa cum o folosești tu, se poate dovedi insuficientă în anumite cazuri. Corect ar fi fost să folosești o coadă circulară, așa cum vom învăța la anul, caz în care lungimea ei era de 100 de poziții. Evitarea "găurilor" este avantajul major al acestei soluții, dar ea se poate face mai simplu, fără cozi. Una peste alta un program solid, funcțional, care are sens. Atenție la duplicarea de cod, în buclă, ea nu e bună. Puteai să tratezi împreună cazurile cînd elementul din matrice este zero sau mai mare ca zero (să incluzi testul de strict mai mare într-un test exterior de mai mare sau egal). Atenție și la modificarea direcției, puteai folosi modulo 4.
  • Teodorescu (72p): Teo, faci un lucru foarte grav: în cadrul unui for modifici atît variabila de ciclu cît și limita ciclului. for este o buclă cu număr cunoscut de pași, nu poți să faci așa ceva, trebuia să folosești while. Caz în care și codul devenea mai simplu și nu te mai încurcai în indici, acolo unde cred că este și problema soluției. Nu așa se folosesc vectorii de direcție. Intenția este ca direcțiile să fie tratate uniform, nemaiavînd nevoie de teste. Urmărește și înțelegi te rog soluția de mai jos. Variabila gata este inutilă, puteai testa direct valoarea lui m.

Problema turn

Comentarii generale

  • Avertismente celor ce nu au trimis nici o soluție la această problemă: Dragomir, Grecu, Iordache.

Problema turn a fost dată la ONI 2007, clasa a 6a.

Rezolvări aici [2]

Tema

Tema 17 clasa a 6a

  • roboți dată la ONI 2006 clasa a 7a (clasa nu e sigură)
  • xy dată la ONI 2011 clasa a 6a

Rezolvări aici [3]