Capitolul 4: Rezolvarea temelorCentrul spiralei
Pentru a ajunge la centrul spiralei în lecția 3, sunt mai multe metode de a rezolva.
Rezolvarea de olimpiadă
Am fost o singură dată la un concurs de informatică. Mi-am dat seama că modul meu preferat de lucru nu se potrivește cerințelor de acolo.
La concursuri, dar și la anumite proiecte, trebuie să faci programe cât mai eficiente și nu contează dacă sunt și flexibile.
Repetând foarte mult cod, dar folosind o singură variabilă, am făcut cel mai simplu și eficient program care rezolvă problema.
var i for (i = 0; i < 6; i=i+1) move() turnRight() for (i = 0; i < 6; i=i+1) move() turnRight() for (i = 0; i < 6; i=i+1) move() turnRight() for (i = 0; i < 5; i=i+1) move() turnRight() for (i = 0; i < 5; i=i+1) move() turnRight() for (i = 0; i < 4; i=i+1) move() turnRight() for (i = 0; i < 4; i=i+1) move() turnRight() for (i = 0; i < 3; i=i+1) move() turnRight() for (i = 0; i < 3; i=i+1) move() turnRight() for (i = 0; i < 2; i=i+1) move() turnRight() for (i = 0; i < 2; i=i+1) move() turnRight() move() turnRight() move()Rezolvarea olimpică
O soluție puțin mai ineficientă (dar digerabilă pentru mine) este să mai punem un for
, care merge descrescător de la 6 la 1.
Unii învățăcei sunt derutați de acel for descrescător, de la linia 8
, însă dacă am fost atenți cum funcționează for
, ar trebui să înțelegem. Într-adevăr, de cele mai multe ori vedem for
crescător.
Transformând din for
în while
, vom vedea:
var m=6
este inițializaream > 0
este condiția de continuarem = m+1
este instrucțiunea de modificare
function superMove(times) { for (var i = 0; i < times; i=i+1) move() } superMove(6) for(var m = 6; m > 0; m = m-1) { turnRight() superMove(m) turnRight() superMove(m) }Rezolvarea aproape-olimpică
În schimb, dacă scopul nostru este să facem un program flexibil, și să ignorăm total eficiența, am putea să facem ceva cu while
.
Codul alăturat va funcționa și dacă s-ar schimba numărul de culoare din spirală.
Cea mai mare problemă a mea aici este că Miorița testează canMove()
de câte două ori consecutiv, la liniile 3
și apoi 1
.
while(canMove()) { move() if (!canMove()) { turnRight() } }Rezolvarea ineficientă
Pentru a evita asta, putem ține răspunsul lui canMove()
într-o variabilă și îi actualizăm valoarea de fiecare dată când se schimbă ceva, fie în urma unei mișcări în față (linia 6
), fie în urma unei rotiri (Linia 10
).
În aceste situații, canMove()
poate da o valoare diferită de ce am stocat în free
.
var free = canMove() while(free) { move() free = canMove() // !! if (!free) { turnRight() free = canMove() // !! } }Rezolvarea flexibilă
În programare, trebuie să alegi ce e mai important pentru aplicația pe care o faci.
Vrei eficiență? Va trebui să dai atenție fiecărui byte de memorie. Dar și atunci poate îți permiți să sacrifici câțiva pentru un program mai ușor de întreținut.
Vrei flexibilitate? Va trebui să te gândești inclusiv la situații posibile din viitor. S-ar putea să nu fie la fel de eficient, dar te poți gândi la ce ai putea face pentru a optimiza puțin, păstrând cât mai mult din flexibilitate.