You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 1-js/06-advanced-functions/01-recursion/01-sum-to/solution.md
+6-6Lines changed: 6 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,4 +1,4 @@
1
-
The solution using a loop:
1
+
Решение с помощью цикла:
2
2
3
3
```js run
4
4
functionsumTo(n) {
@@ -12,7 +12,7 @@ function sumTo(n) {
12
12
alert( sumTo(100) );
13
13
```
14
14
15
-
The solution using recursion:
15
+
Решение через рекурсию:
16
16
17
17
```js run
18
18
functionsumTo(n) {
@@ -23,7 +23,7 @@ function sumTo(n) {
23
23
alert( sumTo(100) );
24
24
```
25
25
26
-
The solution using the formula: `sumTo(n) = n*(n+1)/2`:
26
+
Решение по формуле: `sumTo(n) = n*(n+1)/2`:
27
27
28
28
```js run
29
29
functionsumTo(n) {
@@ -33,8 +33,8 @@ function sumTo(n) {
33
33
alert( sumTo(100) );
34
34
```
35
35
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. Надо ли говорить, что решение по формуле работает быстрее всех? Это очевидно. Оно использует всего три операции для любого n, а цикл и рекурсия требуют как минимум n операций сложения.
37
37
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
+
Вариант с циклом – второй по скорости. Он быстрее рекурсии, так как операций сложения столько же, но нет дополнительных вычислительных затрат на организацию вложенных вызовов. Поэтому рекурсия в данном случае работает медленнее всех.
39
39
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. Некоторые движки поддерживают оптимизацию "хвостового вызова": если рекурсивный вызов является самым последним в функции (как в`sumTo`выше), то внешней функции не нужно будет возобновлять выполнение и не нужно запоминать контекст его выполнения. В итоге требования к памяти снижаются, и сумма`sumTo(100000)`будет успешно вычислена. Но если JavaScript-движок не поддерживает это (большинство не поддерживают), будет ошибка: максимальный размер стека превышен, так как обычно существует ограничение на максимальный размер стека.
Copy file name to clipboardExpand all lines: 1-js/06-advanced-functions/01-recursion/02-factorial/solution.md
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
-
By definition, a factorial is `n!`can be written as`n * (n-1)!`.
1
+
По определению факториал `n!`можно записать как`n * (n-1)!`.
2
2
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`.
4
4
5
5
```js run
6
6
functionfactorial(n) {
@@ -10,7 +10,7 @@ function factorial(n) {
10
10
alert( factorial(5) ); // 120
11
11
```
12
12
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`, однако это добавило рекурсии дополнительный шаг:
Copy file name to clipboardExpand all lines: 1-js/06-advanced-functions/01-recursion/02-factorial/task.md
+6-6Lines changed: 6 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,17 +2,17 @@ importance: 4
2
2
3
3
---
4
4
5
-
# Calculate factorial
5
+
# Вычислить факториал
6
6
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://ru.wikipedia.org/wiki/Факториал) натурального числа - это число, умноженное на `"себя минус один"`, затем на`"себя минус два"`, и так далее до`1`. Факториал `n`обозначается как`n!`
8
8
9
-
We can write a definition of factorial like this:
9
+
Определение факториала можно записать как:
10
10
11
11
```js
12
12
n!= n * (n -1) * (n -2) *...*1
13
13
```
14
14
15
-
Values of factorials for different`n`:
15
+
Примеры значений для разных`n`:
16
16
17
17
```js
18
18
1!=1
@@ -22,10 +22,10 @@ Values of factorials for different `n`:
22
22
5!=5*4*3*2*1=120
23
23
```
24
24
25
-
The task is to write a function `factorial(n)` that calculates`n!` using recursive calls.
25
+
Задача – написать функцию `factorial(n)`, которая возвращает`n!`, используя рекурсию.
26
26
27
27
```js
28
28
alert( factorial(5) ); // 120
29
29
```
30
30
31
-
P.S. Hint: `n!`can be written as `n * (n-1)!`For instance: `3! = 3*2! = 3*2*1! = 6`
The first solution we could try here is the recursive one.
1
+
Сначала решим через рекурсию.
2
2
3
-
Fibonacci numbers are recursive by definition:
3
+
Числа Фибоначчи рекурсивны по определению:
4
4
5
5
```js run
6
6
functionfib(n) {
@@ -9,14 +9,14 @@ function fib(n) {
9
9
10
10
alert( fib(3) ); // 2
11
11
alert( fib(7) ); // 13
12
-
// fib(77); // will be extremely slow!
12
+
// fib(77); // вычисляется очень долго
13
13
```
14
14
15
-
...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.
15
+
При больших значениях `n`такое решение будет работать очень долго. Например, `fib(77)`может повесить браузер на некоторое время, съев все ресурсы процессора.
16
16
17
-
That's because the function makes too many subcalls. The same values are re-evaluated again and again.
17
+
Это потому, что функция порождает обширное дерево вложенных вызовов. При этом ряд значений вычисляется много раз снова и снова.
18
18
19
-
For instance, let's see a piece of calculations for`fib(5)`:
19
+
Например, посмотрим на отрывок вычислений для`fib(5)`:
20
20
21
21
```js no-beautify
22
22
...
@@ -25,68 +25,68 @@ fib(4) = fib(3) + fib(2)
25
25
...
26
26
```
27
27
28
-
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.
28
+
Здесь видно, что значение `fib(3)`нужно одновременно и для `fib(5)`и для `fib(4)`. В коде оно будет вычислено два раза, совершенно независимо.
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`.
34
+
Можно заметить, что `fib(3)`вычисляется дважды, а `fib(2)`- трижды. Общее количество вычислений растёт намного быстрее, чем `n`, что делает его огромным даже для`n=77`.
35
35
36
-
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.
36
+
Можно это оптимизировать, запоминая уже вычисленные значения: если значение, скажем, `fib(3)`вычислено однажды, затем мы просто переиспользуем это значение для последующих вычислений.
37
37
38
-
Another variant would be to give up recursion and use a totally different loop-based algorithm.
38
+
Другим вариантом было бы отказаться от рекурсии и использовать совершенно другой алгоритм на основе цикла.
39
39
40
-
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.
40
+
Вместо того, чтобы начинать с `n`и вычислять необходимые предыдущие значения, можно написать цикл, который начнёт с `1`и`2`, затем из них получит `fib(3)`как их сумму, затем`fib(4)`как сумму предыдущих значений, затем`fib(5)`и так далее, до финального результата. На каждом шаге нам нужно помнить только значения двух предыдущих чисел последовательности.
41
41
42
-
Here are the steps of the new algorithm in details.
42
+
Вот детальные шаги нового алгоритма.
43
43
44
-
The start:
44
+
Начало:
45
45
46
46
```js
47
-
// a = fib(1), b = fib(2), these values are by definition 1
47
+
// a = fib(1), b = fib(2), эти значения по определению равны 1
48
48
let a =1, b =1;
49
49
50
-
//get c = fib(3) as their sum
50
+
//получим c = fib(3) как их сумму
51
51
let c = a + b;
52
52
53
-
/*we now have fib(1), fib(2), fib(3)
53
+
/*теперь у нас есть fib(1), fib(2), fib(3)
54
54
a b c
55
55
1, 1, 2
56
56
*/
57
57
```
58
58
59
-
Now we want to get`fib(4) = fib(2) + fib(3)`.
59
+
Теперь мы хотим получить`fib(4) = fib(2) + fib(3)`.
60
60
61
-
Let's shift the variables: `a,b` will get`fib(2),fib(3)`, and`c`will get their sum:
61
+
Переставим переменные: `a,b`, присвоим значения`fib(2),fib(3)`, тогда`c`можно получить как их сумму:
62
62
63
63
```js no-beautify
64
-
a = b; //now a = fib(2)
65
-
b = c; //now b = fib(3)
64
+
a = b; //теперь a = fib(2)
65
+
b = c; //теперь b = fib(3)
66
66
c = a + b; // c = fib(4)
67
67
68
-
/*now we have the sequence:
68
+
/*имеем последовательность:
69
69
a b c
70
70
1, 1, 2, 3
71
71
*/
72
72
```
73
73
74
-
The next step gives another sequence number:
74
+
Следующий шаг даёт новое число последовательности:
75
75
76
76
```js no-beautify
77
77
a = b; // now a = fib(3)
78
78
b = c; // now b = fib(4)
79
79
c = a + b; // c = fib(5)
80
80
81
-
/*now the sequence is (one more number):
81
+
/*последовательность теперь (на одно число больше):
82
82
a b c
83
83
1, 1, 2, 3, 5
84
84
*/
85
85
```
86
86
87
-
...And so on until we get the needed value. That's much faster than recursion and involves no duplicate computations.
87
+
...И так далее, пока не получим искомое значение. Это намного быстрее рекурсии и не требует повторных вычислений.
88
88
89
-
The full code:
89
+
Полный код:
90
90
91
91
```js run
92
92
functionfib(n) {
@@ -105,6 +105,6 @@ alert( fib(7) ); // 13
105
105
alert( fib(77) ); // 5527939700884757
106
106
```
107
107
108
-
The loop starts with `i=3`, because the first and the second sequence values are hard-coded into variables`a=1`, `b=1`.
108
+
Цикл начинается с `i=3`, потому что первое и второе значения последовательности заданы`a=1`, `b=1`.
109
109
110
-
The approach is called [dynamic programming bottom-up](https://en.wikipedia.org/wiki/Dynamic_programming).
110
+
Такой способ называется [динамическое программирование снизу вверх](https://ru.wikipedia.org/wiki/Динамическое_программирование).
Copy file name to clipboardExpand all lines: 1-js/06-advanced-functions/01-recursion/03-fibonacci-numbers/task.md
+8-8Lines changed: 8 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,24 +2,24 @@ importance: 5
2
2
3
3
---
4
4
5
-
# Fibonacci numbers
5
+
# Числа Фибоначчи
6
6
7
-
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.
7
+
Последовательность [чисел Фибоначчи](https://ru.wikipedia.org/wiki/Числа_Фибоначчи) определяется формулой <code>F<sub>n</sub> = F<sub>n-1</sub> + F<sub>n-2</sub></code>. То есть, следующее число получается как сумма двух предыдущих.
8
8
9
-
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...`.
9
+
Первые два числа равны`1`, затем`2(1+1)`, затем`3(1+2)`, `5(2+3)`и так далее: `1, 1, 2, 3, 5, 8, 13, 21...`.
10
10
11
-
Fibonacci numbers are related to the [Golden ratio](https://en.wikipedia.org/wiki/Golden_ratio) and many natural phenomena around us.
11
+
Числа Фибоначчи тесно связаны с [золотым сечением](https://ru.wikipedia.org/wiki/Золотое_сечение) и множеством природных явлений вокруг нас.
12
12
13
-
Write a function `fib(n)`that returns the `n-th` Fibonacci number.
13
+
Напишите функцию `fib(n)`которая возвращает `n-е` число Фибоначчи.
14
14
15
-
An example of work:
15
+
Пример работы:
16
16
17
17
```js
18
-
functionfib(n) { /*your code*/ }
18
+
functionfib(n) { /*ваш код*/ }
19
19
20
20
alert(fib(3)); // 2
21
21
alert(fib(7)); // 13
22
22
alert(fib(77)); // 5527939700884757
23
23
```
24
24
25
-
P.S. The function should be fast. The call to `fib(77)`should take no more than a fraction of a second.
25
+
P.S. Все запуски функций из примера выше должны работать быстро. Вызов `fib(77)`должен занимать не более доли секунды.
Copy file name to clipboardExpand all lines: 1-js/06-advanced-functions/01-recursion/04-output-single-linked-list/solution.md
+13-13Lines changed: 13 additions & 13 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
-
# Loop-based solution
1
+
# Решение с использованием цикла
2
2
3
-
The loop-based variant of the solution:
3
+
Решение с использованием цикла:
4
4
5
5
```js run
6
6
let list = {
@@ -30,7 +30,7 @@ function printList(list) {
30
30
printList(list);
31
31
```
32
32
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`вместо неё:
34
34
35
35
```js
36
36
functionprintList(list) {
@@ -43,15 +43,15 @@ function printList(list) {
43
43
}
44
44
```
45
45
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 loose such ability.
46
+
...Но это было бы неблагоразумно. В будущем нам может понадобиться расширить функцию, сделать что-нибудь ещё со списком. Если мы меняем`list`, то теряем такую возможность.
47
47
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`здесь - это сам список, его первый элемент. Так и должно быть, это просто и понятно.
49
49
50
-
From the other side, the role of `tmp`is exclusively a list traversal, like`i`in the`for` loop.
50
+
С другой стороны, `tmp`используется исключительно для обхода списка, как`i`в цикле`for`.
51
51
52
-
# Recursive solution
52
+
# Решение через рекурсию
53
53
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`:
55
55
56
56
```js run
57
57
let list = {
@@ -70,19 +70,19 @@ let list = {
70
70
71
71
functionprintList(list) {
72
72
73
-
alert(list.value); //output the current item
73
+
alert(list.value); //выводим текущий элемент
74
74
75
75
if (list.next) {
76
-
printList(list.next); //do the same for the rest of the list
76
+
printList(list.next); //делаем то же самое для остальной части списка
77
77
}
78
78
79
79
}
80
80
81
81
printList(list);
82
82
```
83
83
84
-
Now what's better?
84
+
Какой способ лучше?
85
85
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
+
Технически, способ с циклом более эффективный. В обеих реализациях делается то же самое, но для цикла не тратятся ресурсы для вложенных вызовов.
87
87
88
-
From the other side, the recursive variant is shorter and sometimes easier to understand.
88
+
С другой стороны, рекурсивный вариант более короткий и, возможно, более простой для понимания.
0 commit comments