Appearance
Conversia din pentru în repeta ... pana cand
De unde pornim?
Știm deja că pentru face automat 3 lucruri în spate. La conversia în cat timp le-am făcut pe toate 3 manual. repeta ... pana cand funcționează similar, dar cu două diferențe importante față de cat timp:
- Testul are loc la final, nu la început
- Bucla continuă cât timp condiția e falsă — se oprește când devine adevărată
Aceste două diferențe ne obligă să ajustăm conversia.
Luăm același punct de plecare:
┌ pentru i ← 1, n executa
│ <instructiuni>
└■Și reamintim cum arăta desfăcut:
i ← 1 → initializare
cat timp i ≤ n → test la INCEPUT, continua cat timp e ADEVARAT
<instructiuni>
i ← i + 1 → incrementarePasul 1 — Inițializarea (identic cu cat timp)
Același raționament: repeta nu știe nimic despre variabilă, deci o inițializăm noi, înainte de buclă.
i ← 1
┌ repeta
│ ...
└ pana cand ...Pasul 2 — Condiția (atenție: se inversează!)
Aceasta este diferența cheie față de conversia în cat timp.
La cat timp am scris condiția direct: „continuă cât timp i ≤ n".
La repeta ... pana cand sensul este invers: „oprește-te când condiția devine adevărată". Deci trebuie să scriem opusul condiției de continuare:
cat timp i ≤ n → pana cand i > nCu alte cuvinte: bucla se repeta până când i a depășit n.
i ← 1
┌ repeta
│ ...
└ pana cand i > nPasul 3 — Incrementarea (identic cu cat timp)
La fel ca înainte, incrementăm manual la sfârșitul corpului, pentru a păstra ordinea: mai întâi instrucțiunile, abia după incrementare.
i ← 1
┌ repeta
│ <instructiuni>
│ i ← i + 1
└ pana cand i > nRezultatul final
// pentru:
┌ pentru i ← 1, n executa
│ <instructiuni>
└■
// repeta echivalent:
i ← 1 ← Pasul 1: initializam noi
┌ repeta
│ <instructiuni>
│ i ← i + 1 ← Pasul 3: incrementam noi, la final
└ pana cand i > n ← Pasul 2: opusul conditiei de continuareAtenție: o problemă ascunsă!
Spre deosebire de cat timp, instrucțiunea repeta execută corpul cel puțin o dată, indiferent de condiție. Aceasta înseamnă că cele două variante nu sunt întotdeauna echivalente.
Pentru a fi complet echivalente, conversia corectă este:
i ← 1
┌ daca i ≤ n atunci
│ ┌ repeta
│ │ <instructiuni>
│ │ i ← i + 1
│ └ pana cand i > n
└■Instrucțiunea daca ne asigura ca testam inainte sa executam bucla (la fel ca la cat timp) — dacă de la început n este 0 atunci i > n si corpul nu se execută deloc, exact ca la pentru.
Ce se schimbă când pasul este negativ?
Același raționament, în sens invers. Condiția de continuare a pentru cu pas -1 este i ≥ expresie_finala, deci opusul ei (pentru pana cand) este i < expresie_finala:
// pentru:
┌ pentru i ← n, 1, -1 executa
│ <instructiuni>
└■
// repeta echivalent (cu protectie):
i ← n
┌ daca i ≥ 1 atunci
│ ┌ repeta
│ │ <instructiuni>
│ │ i ← i - 1
│ └ pana cand i < 1
└■Regula generală
- Inițializează variabila înainte de buclă — la fel ca la
cat timp - Inversează condiția de continuare și pune-o în
pana cand— spre deosebire decat timp, unde o copiai direct - Incrementează / decrementează manual la sfârșitul corpului — la fel ca la
cat timp - Adaugă un
dacacare să protejeze bucla pentru cazul în care intervalul e gol
Exemplu complet
Problema: Suma primelor n numere naturale.
// Cu pentru:
citeste n
S ← 0
┌ pentru i ← 1, n executa
│ S ← S + i
└■
scrie S
// Cu repeta (aplicand cei 3 pasi + protectie):
citeste n
S ← 0
i ← 1 ← Pasul 1
┌ daca i ≤ n atunci
│ ┌ repeta
│ │ S ← S + i
│ │ i ← i + 1 ← Pasul 3
│ └ pana cand i > n ← Pasul 2: opusul lui i ≤ n
└■
scrie S