Skip to content
12 changes: 6 additions & 6 deletions 1-js/06-advanced-functions/01-recursion/01-sum-to/solution.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
The solution using a loop:
Soluția folosind un loop:

```js run
function sumTo(n) {
Expand All @@ -12,7 +12,7 @@ function sumTo(n) {
alert( sumTo(100) );
```

The solution using recursion:
Soluția folosind recursivitatea:

```js run
function sumTo(n) {
Expand All @@ -23,7 +23,7 @@ function sumTo(n) {
alert( sumTo(100) );
```

The solution using the formula: `sumTo(n) = n*(n+1)/2`:
Soluția folosind formula: `sumTo(n) = n*(n+1)/2`:

```js run
function sumTo(n) {
Expand All @@ -33,8 +33,8 @@ function sumTo(n) {
alert( sumTo(100) );
```

P.S. Naturally, the formula is the fastest solution. It uses only 3 operations for any number `n`. The math helps!
P.S. Firește, formula este cea mai rapidă soluție. Ea folosește doar 3 operații pentru orice număr `n`. Matematica ajută!

The loop variant is the second in terms of speed. In both the recursive and the loop variant we sum the same numbers. But the recursion involves nested calls and execution stack management. That also takes resources, so it's slower.
Varianta cu bucle este a doua în ceea ce privește viteza. Atât în varianta recursivă cât și în varianta loop adunăm aceleași numere. Dar recursivitatea implică apeluri nested și gestionare de execution stack. Și asta necesită resurse, deci este mai lent.

P.P.S. Some engines support the "tail call" optimization: if a recursive call is the very last one in the function, with no other calculations performed, then the outer function will not need to resume the execution, so the engine doesn't need to remember its execution context. That removes the burden on memory. But if the JavaScript engine does not support tail call optimization (most of them don't), there will be an error: maximum stack size exceeded, because there's usually a limitation on the total stack size.
P.P.S. Unele motoare suportă optimizarea "tail call": dacă un apel recursiv este chiar ultimul din funcție, fără alte calcule efectuate, atunci funcția exterioară nu va trebui să reia execuția, astfel încât motorul nu trebuie să își amintească contextul de execuție. Asta elimină povara asupra memoriei. Dar dacă motorul JavaScript nu acceptă optimizarea tail call (majoritatea nu o fac), va apărea o eroare: maximum stack size exceeded, deoarece există de obicei o limitare a dimensiunii totale din stack.
22 changes: 11 additions & 11 deletions 1-js/06-advanced-functions/01-recursion/01-sum-to/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ importance: 5

---

# Sum all numbers till the given one
# Însumați toate numerele până la cel dat

Write a function `sumTo(n)` that calculates the sum of numbers `1 + 2 + ... + n`.
Scrieți o funcție `sumTo(n)` care calculează suma numerelor `1 + 2 + ... + n`.

For instance:
De exemplu:

```js no-beautify
sumTo(1) = 1
Expand All @@ -17,20 +17,20 @@ sumTo(4) = 4 + 3 + 2 + 1 = 10
sumTo(100) = 100 + 99 + ... + 2 + 1 = 5050
```

Make 3 solution variants:
Faceți 3 variante de soluție:

1. Using a for loop.
2. Using a recursion, cause `sumTo(n) = n + sumTo(n-1)` for `n > 1`.
3. Using the [arithmetic progression](https://en.wikipedia.org/wiki/Arithmetic_progression) formula.
1. Folosind un for loop.
2. Folosind o recursiune, cauza `sumTo(n) = n + sumTo(n-1)` pentru `n > 1`.
3. Folosind formula de [progresie aritmetică](https://en.wikipedia.org/wiki/Arithmetic_progression).

An example of the result:
Un exemplu de rezultat:

```js
function sumTo(n) { /*... your code ... */ }
function sumTo(n) { /*... codul tău ... */ }

alert( sumTo(100) ); // 5050
```

P.S. Which solution variant is the fastest? The slowest? Why?
P.S. Care variantă de soluție este cea mai rapidă? Cea mai lentă? De ce?

P.P.S. Can we use recursion to count `sumTo(100000)`?
P.P.S. Putem folosi recursivitatea pentru a număra `sumTo(100000)`?
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
By definition, a factorial `n!` can be written as `n * (n-1)!`.
Prin definiție, un factorial `n!` poate fi scris ca `n * (n-1)!`.

In other words, the result of `factorial(n)` can be calculated as `n` multiplied by the result of `factorial(n-1)`. And the call for `n-1` can recursively descend lower, and lower, till `1`.
Cu alte cuvinte, rezultatul `factorial(n)` poate fi calculat ca `n` înmulțit cu rezultatul lui `factorial(n-1)`. Iar apelul pentru `n-1` poate coborâ recursiv tot mai jos, tot mai jos, până la `1`.

```js run
function factorial(n) {
Expand All @@ -10,7 +10,7 @@ function factorial(n) {
alert( factorial(5) ); // 120
```

The basis of recursion is the value `1`. We can also make `0` the basis here, doesn't matter much, but gives one more recursive step:
Baza recursivității este valoarea `1`. De asemenea putem face ca `0` să fie baza aici, nu contează prea mult, dar oferă încă un pas recursiv:

```js run
function factorial(n) {
Expand Down
12 changes: 6 additions & 6 deletions 1-js/06-advanced-functions/01-recursion/02-factorial/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ importance: 4

---

# Calculate factorial
# Calculează factorialul

The [factorial](https://en.wikipedia.org/wiki/Factorial) of a natural number is a number multiplied by `"number minus one"`, then by `"number minus two"`, and so on till `1`. The factorial of `n` is denoted as `n!`
[Factorialul](https://en.wikipedia.org/wiki/Factorial) unui număr natural este un număr înmulțit cu `"numărul minus unu"`, apoi cu `"numărul minus doi"`, și așa mai departe până la `1`. Factorialul lui `n` se notează cu `n!`.

We can write a definition of factorial like this:
Putem scrie o definiție a factorialului în felul următor:

```js
n! = n * (n - 1) * (n - 2) * ...*1
```

Values of factorials for different `n`:
Valori ale factorialelor pentru diferite `n`:

```js
1! = 1
Expand All @@ -22,10 +22,10 @@ Values of factorials for different `n`:
5! = 5 * 4 * 3 * 2 * 1 = 120
```

The task is to write a function `factorial(n)` that calculates `n!` using recursive calls.
Sarcina este de a scrie o funcție `factorial(n)` care să calculeze `n!` folosind apeluri recursive.

```js
alert( factorial(5) ); // 120
```

P.S. Hint: `n!` can be written as `n * (n-1)!` For instance: `3! = 3*2! = 3*2*1! = 6`
P.S. Indiciu: `n!` poate fi scris ca `n * (n-1)!` De exemplu: `3! = 3*2! = 3*2*1! = 6`
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The first solution we could try here is the recursive one.
Prima soluție pe care am putea-o încerca aici este cea recursivă.

Fibonacci numbers are recursive by definition:
Numerele Fibonacci sunt recursive prin definiție:

```js run
function fib(n) {
Expand All @@ -9,14 +9,14 @@ function fib(n) {

alert( fib(3) ); // 2
alert( fib(7) ); // 13
// fib(77); // will be extremely slow!
// fib(77); // va fi extrem de lent!
```

...But for big values of `n` it's very slow. For instance, `fib(77)` may hang up the engine for some time eating all CPU resources.
...Dar pentru valori mari ale lui `n` este foarte lent. De exemplu, `fib(77)` poate bloca motorul pentru o perioadă de timp, consumând toate resursele CPU.

That's because the function makes too many subcalls. The same values are re-evaluated again and again.
Asta pentru că funcția face prea multe subapelări. Aceleași valori sunt reevaluate din nou și din nou.

For instance, let's see a piece of calculations for `fib(5)`:
De exemplu, să vedem o bucată de calcule pentru `fib(5)`:

```js no-beautify
...
Expand All @@ -25,68 +25,68 @@ fib(4) = fib(3) + fib(2)
...
```

Here we can see that the value of `fib(3)` is needed for both `fib(5)` and `fib(4)`. So `fib(3)` will be called and evaluated two times completely independently.
Aici putem vedea că valoarea lui `fib(3)` este necesară atât pentru `fib(5)` cât și pentru `fib(4)`. Deci `fib(3)` va fi apelat și evaluat de două ori în mod complet independent.

Here's the full recursion tree:
Iată arborele de recursivitate complet:

![fibonacci recursion tree](fibonacci-recursion-tree.svg)

We can clearly notice that `fib(3)` is evaluated two times and `fib(2)` is evaluated three times. The total amount of computations grows much faster than `n`, making it enormous even for `n=77`.
Putem observa în mod clar că `fib(3)` este evaluat de două ori, iar `fib(2)` este evaluat de trei ori. Suma totală a calculelor crește mult mai repede decât `n`, devenind enormă chiar și pentru `n=77`.

We can optimize that by remembering already-evaluated values: if a value of say `fib(3)` is calculated once, then we can just reuse it in future computations.
Putem optimiza acest lucru prin memorarea valorilor deja evaluate: dacă o valoare de exemplu `fib(3)` este calculată o dată, atunci o putem reutiliza în calculele viitoare.

Another variant would be to give up recursion and use a totally different loop-based algorithm.
O altă variantă ar fi să renunțăm la recursivitate și să folosim un algoritm complet diferit bazat pe loop.

Instead of going from `n` down to lower values, we can make a loop that starts from `1` and `2`, then gets `fib(3)` as their sum, then `fib(4)` as the sum of two previous values, then `fib(5)` and goes up and up, till it gets to the needed value. On each step we only need to remember two previous values.
În loc să mergem de la `n` în jos la valori mai mici, putem face un loop care pornește de la `1` și `2`, apoi obține `fib(3)` ca sumă a acestora, apoi `fib(4)` ca sumă a două valori anterioare, apoi `fib(5)` și merge în sus și în sus, până când ajunge la valoarea necesară. La fiecare pas trebuie să ne amintim doar două valori anterioare.

Here are the steps of the new algorithm in details.
Iată pașii noului algoritm în detaliu.

The start:
Începutul:

```js
// a = fib(1), b = fib(2), these values are by definition 1
// a = fib(1), b = fib(2), aceste valori sunt prin definiție 1
let a = 1, b = 1;

// get c = fib(3) as their sum
// obțineți c = fib(3) ca sumă a acestora
let c = a + b;

/* we now have fib(1), fib(2), fib(3)
/* acum avem fib(1), fib(2), fib(3)
a b c
1, 1, 2
*/
```

Now we want to get `fib(4) = fib(2) + fib(3)`.
Acum dorim să obținem `fib(4) = fib(2) + fib(3)`.

Let's shift the variables: `a,b` will get `fib(2),fib(3)`, and `c` will get their sum:
Să schimbăm variabilele: `a,b` vor obține `fib(2),fib(3)`, iar `c` va obține suma lor:

```js no-beautify
a = b; // now a = fib(2)
b = c; // now b = fib(3)
a = b; // acum a = fib(2)
b = c; // acum b = fib(3)
c = a + b; // c = fib(4)

/* now we have the sequence:
/* acum avem secvența:
a b c
1, 1, 2, 3
*/
```

The next step gives another sequence number:
Următorul pas oferă un alt număr de secvență:

```js no-beautify
a = b; // now a = fib(3)
b = c; // now b = fib(4)
a = b; // acum a = fib(3)
b = c; // acum b = fib(4)
c = a + b; // c = fib(5)

/* now the sequence is (one more number):
/* acum secvența este (încă un număr):
a b c
1, 1, 2, 3, 5
*/
```

...And so on until we get the needed value. That's much faster than recursion and involves no duplicate computations.
...Și așa mai departe până când obținem valoarea necesară. Acest lucru este mult mai rapid decât recursivitatea și nu implică calcule duplicate.

The full code:
Codul complet:

```js run
function fib(n) {
Expand All @@ -105,6 +105,6 @@ alert( fib(7) ); // 13
alert( fib(77) ); // 5527939700884757
```

The loop starts with `i=3`, because the first and the second sequence values are hard-coded into variables `a=1`, `b=1`.
Bucla începe cu `i=3`, deoarece prima și a doua valoare a secvenței sunt hard-coded în variabilele `a=1`, `b=1`.

The approach is called [dynamic programming bottom-up](https://en.wikipedia.org/wiki/Dynamic_programming).
Abordarea se numește [programare dinamică de jos în sus](https://en.wikipedia.org/wiki/Dynamic_programming).
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,24 @@ importance: 5

---

# Fibonacci numbers
# Numere Fibonacci

The sequence of [Fibonacci numbers](https://en.wikipedia.org/wiki/Fibonacci_number) has the formula <code>F<sub>n</sub> = F<sub>n-1</sub> + F<sub>n-2</sub></code>. In other words, the next number is a sum of the two preceding ones.
Secvența [numerelor Fibonacci](https://en.wikipedia.org/wiki/Fibonacci_number) are formula <code>F<sub>n</sub> = F<sub>n-1</sub> + F<sub>n-2</sub></code>. Cu alte cuvinte, următorul număr este suma celor două numere precedente.

First two numbers are `1`, then `2(1+1)`, then `3(1+2)`, `5(2+3)` and so on: `1, 1, 2, 3, 5, 8, 13, 21...`.
Primele două numere sunt `1`, apoi `2(1+1)`, apoi `3(1+2)`, `5(2+3)` și așa mai departe: `1, 1, 2, 3, 5, 8, 13, 21...`.

Fibonacci numbers are related to the [Golden ratio](https://en.wikipedia.org/wiki/Golden_ratio) and many natural phenomena around us.
Numerele Fibonacci sunt legate de [Golden ratio](https://en.wikipedia.org/wiki/Golden_ratio) și de multe fenomene naturale din jurul nostru.

Write a function `fib(n)` that returns the `n-th` Fibonacci number.
Scrieți o funcție `fib(n)` care să returneze al `n-lea` număr Fibonacci.

An example of work:
Un exemplu de lucrare:

```js
function fib(n) { /* your code */ }
function fib(n) { /* codul tău */ } }

alert(fib(3)); // 2
alert(fib(7)); // 13
alert(fib(77)); // 5527939700884757
```

P.S. The function should be fast. The call to `fib(77)` should take no more than a fraction of a second.
P.S. Funcția ar trebui să fie rapidă. Apelul la `fib(77)` nu ar trebui să dureze mai mult de o fracțiune de secundă.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Loop-based solution
# Soluție bazată pe loop

The loop-based variant of the solution:
Varianta soluției bazată pe loop:

```js run
let list = {
Expand Down Expand Up @@ -30,7 +30,7 @@ function printList(list) {
printList(list);
```

Please note that we use a temporary variable `tmp` to walk over the list. Technically, we could use a function parameter `list` instead:
Vă rugăm să rețineți că folosim o variabilă temporară `tmp` pentru a parcurge lista. Din punct de vedere tehnic, am putea folosi în schimb un parametru de funcție `list`:

```js
function printList(list) {
Expand All @@ -43,15 +43,15 @@ function printList(list) {
}
```

...But that would be unwise. In the future we may need to extend a function, do something else with the list. If we change `list`, then we lose such ability.
...Dar asta ar fi neînțelept. În viitor s-ar putea să avem nevoie să extindem o funcție, să facem altceva cu lista. Dacă schimbăm `list`, atunci pierdem o astfel de abilitate.

Talking about good variable names, `list` here is the list itself. The first element of it. And it should remain like that. That's clear and reliable.
Vorbind despre nume de variabile bune, `list` aici este lista însăși. Primul element al acesteia. Și ar trebui să rămână așa. Este clar și de încredere.

From the other side, the role of `tmp` is exclusively a list traversal, like `i` in the `for` loop.
De cealaltă parte, rolul lui `tmp` este exclusiv o traversare a listei, ca și `i` în bucla `for`.

# Recursive solution
# Soluție recursivă

The recursive variant of `printList(list)` follows a simple logic: to output a list we should output the current element `list`, then do the same for `list.next`:
Varianta recursivă a `printList(list)` urmează o logică simplă: pentru a scoate o listă trebuie să scoatem elementul curent `list`, apoi să facem același lucru pentru `list.next`:

```js run
let list = {
Expand All @@ -70,19 +70,19 @@ let list = {

function printList(list) {

alert(list.value); // output the current item
alert(list.value); // afișează elementul curent

if (list.next) {
printList(list.next); // do the same for the rest of the list
printList(list.next); // procedează la fel pentru restul listei
}

}

printList(list);
```

Now what's better?
Acum ce este mai bine?

Technically, the loop is more effective. These two variants do the same, but the loop does not spend resources for nested function calls.
Din punct de vedere tehnic, un loop este mai eficient. Aceste două variante fac același lucru, dar loop-ul nu consumă resurse pentru apeluri de funcții nested.

From the other side, the recursive variant is shorter and sometimes easier to understand.
De partea cealaltă, varianta recursivă este mai scurtă și uneori mai ușor de înțeles.
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ importance: 5

---

# Output a single-linked list
# Scoate un singur linked list

Let's say we have a single-linked list (as described in the chapter <info:recursion>):
Să presupunem că avem un singur linked list (așa cum este descris în capitolul <info:recursion>):

```js
let list = {
Expand All @@ -22,8 +22,8 @@ let list = {
};
```

Write a function `printList(list)` that outputs list items one-by-one.
Scrieți o funcție `printList(list)` care scoate elementele din listă unul câte unul.

Make two variants of the solution: using a loop and using recursion.
Realizați două variante ale soluției: folosind un loop și folosind recursivitatea.

What's better: with recursion or without it?
Ce este mai bine: cu recursivitate sau fără ea?
Loading