Skip to content

Commit 41625a9

Browse files
authored
Recursion and stack (#201)
1 parent 925ff83 commit 41625a9

File tree

10 files changed

+217
-217
lines changed

10 files changed

+217
-217
lines changed

1-js/06-advanced-functions/01-recursion/01-sum-to/solution.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
The solution using a loop:
1+
Рішення з використанням циклу:
22

33
```js run
44
function sumTo(n) {
@@ -12,7 +12,7 @@ function sumTo(n) {
1212
alert( sumTo(100) );
1313
```
1414

15-
The solution using recursion:
15+
Рішення з використанням рекурсії:
1616

1717
```js run
1818
function sumTo(n) {
@@ -23,7 +23,7 @@ function sumTo(n) {
2323
alert( sumTo(100) );
2424
```
2525

26-
The solution using the formula: `sumTo(n) = n*(n+1)/2`:
26+
Рішення з використанням формули: `sumTo(n) = n*(n+1)/2`:
2727

2828
```js run
2929
function sumTo(n) {
@@ -33,8 +33,8 @@ function sumTo(n) {
3333
alert( sumTo(100) );
3434
```
3535

36-
P.S. Naturally, the formula is the fastest solution. It uses only 3 operations for any number `n`. The math helps!
36+
P.S. Звичайно, формула є найшвидшим рішенням. Вона використовує лише 3 операції для будь-якого числа `n`. Математика допомагає!
3737

38-
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.
38+
Варіант з циклом є другим з точки зору швидкості. Як і у випадку рекурсії, в циклі ми сумуємо ті ж числа. Але рекурсія передбачає вкладені виклики та управління стеком. Це також займає ресурси, тому це повільніше.
3939

40-
P.P.S. Some engines support the "tail call" optimization: if a recursive call is the very last one in the function (like in `sumTo` above), 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, so counting `sumTo(100000)` becomes possible. 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.
40+
P.P.S. Деякі рушії підтримують оптимізацію "хвостового виклику" (tail call): якщо рекурсивний виклик є останнім в функції (як у випадку з `sumTo`), то зовнішня функція не повинна відновлювати виконання, отже рушію не потрібно запам’ятовувати контекст виконання. Це зменшує використання пам’яті, тому підрахунок `sumTo(100000)` стає можливим. Але якщо рушій JavaScript не підтримує оптимізацію хвостового виклику (більшість з них не підтримує), то виникне помилка: максимальний розмір стека перевищиться, оскільки зазвичай є обмеження на загальний розмір стека.

1-js/06-advanced-functions/01-recursion/01-sum-to/task.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ importance: 5
22

33
---
44

5-
# Sum all numbers till the given one
5+
# Сума всіх чисел до даного
66

7-
Write a function `sumTo(n)` that calculates the sum of numbers `1 + 2 + ... + n`.
7+
Напишіть функцію `sumTo(n)`, що обчислює суму чисел `1 + 2 + ... + n`.
88

9-
For instance:
9+
Наприклад:
1010

1111
```js no-beautify
1212
sumTo(1) = 1
@@ -17,20 +17,20 @@ sumTo(4) = 4 + 3 + 2 + 1 = 10
1717
sumTo(100) = 100 + 99 + ... + 2 + 1 = 5050
1818
```
1919

20-
Make 3 solution variants:
20+
Зробити 3 варіанти рішення:
2121

22-
1. Using a for loop.
23-
2. Using a recursion, cause `sumTo(n) = n + sumTo(n-1)` for `n > 1`.
24-
3. Using the [arithmetic progression](https://en.wikipedia.org/wiki/Arithmetic_progression) formula.
22+
1. Використання циклу.
23+
2. Використання рекурсії, у випадку `sumTo(n) = n + sumTo(n-1)` для `n > 1`.
24+
3. Використання формули [арифметичної прогресії] (https://uk.wikipedia.org/wiki/Арифметична_прогресія).
2525

26-
An example of the result:
26+
Приклад результату:
2727

2828
```js
29-
function sumTo(n) { /*... your code ... */ }
29+
function sumTo(n) { /*... ваш код ... */ }
3030

3131
alert( sumTo(100) ); // 5050
3232
```
3333

34-
P.S. Which solution variant is the fastest? The slowest? Why?
34+
P.S. Який варіант рішення є найшвидшим? Найповільнішим? Чому?
3535

36-
P.P.S. Can we use recursion to count `sumTo(100000)`?
36+
P.P.S. Чи можемо ми використовувати рекурсію для підрахунку `sumTo(100000)`?

1-js/06-advanced-functions/01-recursion/02-factorial/solution.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
By definition, a factorial `n!` can be written as `n * (n-1)!`.
1+
За визначенням, факторіал `n!` може бути записаний як `n * (n-1)!`.
22

3-
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`.
3+
Інакше кажучи, результат `factorial(n)` може бути розрахований, як `n` помножений на результат `factorial(n-1)`. І виклик до `n-1` може рекурсивно спускатися нижче та нижче, аж до `1`.
44

55
```js run
66
function factorial(n) {
@@ -10,7 +10,7 @@ function factorial(n) {
1010
alert( factorial(5) ); // 120
1111
```
1212

13-
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:
13+
Базисом рекурсії є значення `1`. Ми також можемо зробити `0` базисом, це не має великого значення, але дає ще один рекурсивний крок:
1414

1515
```js run
1616
function factorial(n) {

1-js/06-advanced-functions/01-recursion/02-factorial/task.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@ importance: 4
22

33
---
44

5-
# Calculate factorial
5+
# Розрахувати факторіал
66

7-
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!`
7+
[Факторіал](https://uk.wikipedia.org/wiki/Факторіал) з натурального числа -- це число, помножене на `"число мінус один"`, потім на `"число мінус два"` і так до `1`. Факторіал `n` позначається як `n!`
88

9-
We can write a definition of factorial like this:
9+
Ми можемо написати визначення факторіалу наступним чином:
1010

1111
```js
1212
n! = n * (n - 1) * (n - 2) * ...*1
1313
```
1414

15-
Values of factorials for different `n`:
15+
Значення факторіалів для різних `n`:
1616

1717
```js
1818
1! = 1
@@ -22,10 +22,10 @@ Values of factorials for different `n`:
2222
5! = 5 * 4 * 3 * 2 * 1 = 120
2323
```
2424

25-
The task is to write a function `factorial(n)` that calculates `n!` using recursive calls.
25+
Завдання полягає в тому, щоб написати функцію `factorial(n)`, яка обчислює `n!` за допомогою рекурсивних викликів.
2626

2727
```js
2828
alert( factorial(5) ); // 120
2929
```
3030

31-
P.S. Hint: `n!` can be written as `n * (n-1)!` For instance: `3! = 3*2! = 3*2*1! = 6`
31+
P.S. Підказка: `n!` може бути записане як `n * (n-1)!`. Наприклад: `3! = 3*2! = 3*2*1! = 6`

1-js/06-advanced-functions/01-recursion/04-output-single-linked-list/solution.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# Loop-based solution
1+
# Рішення на основі циклу
22

3-
The loop-based variant of the solution:
3+
Варіант рішення на основі циклу:
44

55
```js run
66
let list = {
@@ -30,7 +30,7 @@ function printList(list) {
3030
printList(list);
3131
```
3232

33-
Please note that we use a temporary variable `tmp` to walk over the list. Technically, we could use a function parameter `list` instead:
33+
Зверніть увагу, що ми використовуємо тимчасову змінну `tmp`, щоб пройти по списку. Технічно ми могли б використовувати замість нього параметр функції `list`:
3434

3535
```js
3636
function printList(list) {
@@ -43,15 +43,15 @@ function printList(list) {
4343
}
4444
```
4545

46-
...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.
46+
...Але це було б нерозумно. У майбутньому нам доведеться розширити функцію, зробити щось інше з `list`. Якщо ми змінюємо `list`, то ми втрачаємо таку здатність.
4747

48-
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.
48+
Говорячи про хороші імена змінних, `list` тут -- це сам список. Його перший елемент. І це повинно залишитися так. Це ясно і надійний.
4949

50-
From the other side, the role of `tmp` is exclusively a list traversal, like `i` in the `for` loop.
50+
З іншого боку, `tmp` використовується виключно проходу, як `i` у `for` циклі.
5151

52-
# Recursive solution
52+
# Рішення через рекурсію
5353

54-
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`:
54+
Рекурсивний варіант `printlist(list)` слідує простій логіці: вивести список, який ми повинні вивести поточний елемент `list`, а потім зробити те ж саме для` list.next`:
5555

5656
```js run
5757
let list = {
@@ -70,19 +70,19 @@ let list = {
7070

7171
function printList(list) {
7272

73-
alert(list.value); // output the current item
73+
alert(list.value); // виведіть поточний елемент
7474

7575
if (list.next) {
76-
printList(list.next); // do the same for the rest of the list
76+
printList(list.next); // зробіть те ж саме для решти списку
7777
}
7878

7979
}
8080

8181
printList(list);
8282
```
8383

84-
Now what's better?
84+
Що ж тепер краще?
8585

86-
Technically, the loop is more effective. These two variants do the same, but the loop does not spend resources for nested function calls.
86+
Технічно цикл є більш ефективним. Ці два варіанти роблять те ж саме, але цикл не витрачає ресурси для вкладених викликів.
8787

88-
From the other side, the recursive variant is shorter and sometimes easier to understand.
88+
З іншого боку, рекурсивний варіант коротший, а іноді його легше зрозуміти.

1-js/06-advanced-functions/01-recursion/04-output-single-linked-list/task.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ importance: 5
22

33
---
44

5-
# Output a single-linked list
5+
# Вивести одинозв’язаний список
66

7-
Let's say we have a single-linked list (as described in the chapter <info:recursion>):
7+
Скажімо, у нас є одинозв’язаний список (як описано в розділі <info:recursion>):
88

99
```js
1010
let list = {
@@ -22,8 +22,8 @@ let list = {
2222
};
2323
```
2424

25-
Write a function `printList(list)` that outputs list items one-by-one.
25+
Напишіть функцію `printList(list)`, що виводить список елементів один за одним.
2626

27-
Make two variants of the solution: using a loop and using recursion.
27+
Зробіть два варіанти рішення: з використанням циклу та з використанням рекурсії.
2828

29-
What's better: with recursion or without it?
29+
Що краще: з рекурсією чи без неї?

1-js/06-advanced-functions/01-recursion/05-output-single-linked-list-reverse/solution.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
# Using a recursion
1+
# Використання рекурсії
22

3-
The recursive logic is a little bit tricky here.
3+
Тут рекурсивна логіка трохи складна.
44

5-
We need to first output the rest of the list and *then* output the current one:
5+
Нам потрібно спочатку вивести останні елементи списку, а *потім* вивести поточний:
66

77
```js run
88
let list = {
@@ -31,13 +31,13 @@ function printReverseList(list) {
3131
printReverseList(list);
3232
```
3333

34-
# Using a loop
34+
# За допомогою циклу
3535

36-
The loop variant is also a little bit more complicated then the direct output.
36+
Варіант циклу також трохи складніше, ніж прямий вивід.
3737

38-
There is no way to get the last value in our `list`. We also can't "go back".
38+
Немає можливості отримати останнє значення в нашому `list`. Ми також не можемо "повернутися назад".
3939

40-
So what we can do is to first go through the items in the direct order and remember them in an array, and then output what we remembered in the reverse order:
40+
Отже, що ми можемо зробити, так це спочатку пройти елементи в прямому порядку і запам’ятати їх у масиві, а потім вивести те, що ми запам’ятали, в зворотному порядку:
4141

4242
```js run
4343
let list = {
@@ -71,4 +71,4 @@ function printReverseList(list) {
7171
printReverseList(list);
7272
```
7373

74-
Please note that the recursive solution actually does exactly the same: it follows the list, remembers the items in the chain of nested calls (in the execution context stack), and then outputs them.
74+
Зверніть увагу, що рекурсивне рішення фактично робить точно так само: проходиться списком, запам’ятовує елементи в ланцюжку вкладених викликів (у контекстному стеку виконання), а потім виводить їх.

1-js/06-advanced-functions/01-recursion/05-output-single-linked-list-reverse/task.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ importance: 5
22

33
---
44

5-
# Output a single-linked list in the reverse order
5+
# Вивести одинозв’язаний список у зворотному порядку
66

7-
Output a single-linked list from the previous task <info:task/output-single-linked-list> in the reverse order.
7+
Виведіть одинозв’язаний список з попереднього завдання <info:task/output-single-linked-list> у зворотному порядку.
88

9-
Make two solutions: using a loop and using a recursion.
9+
Зробіть два рішення: за допомогою циклу та з використанням рекурсії.

0 commit comments

Comments
 (0)