Skip to content

Commit 5d6ab16

Browse files
authored
Merge pull request #76 from Adham-Niazy/master
Recursion and Stack
2 parents 06be139 + d962c6d commit 5d6ab16

File tree

11 files changed

+267
-230
lines changed

11 files changed

+267
-230
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) {
@@ -22,8 +22,8 @@ function sumTo(n) {
2222

2323
alert( sumTo(100) );
2424
```
25+
الحل بإستخدام هذه المعادلة: `sumTo(n) = n*(n+1)/2`:
2526

26-
The solution using the formula: `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+
1. منطقياً حل المعادلة هو أسرع حل لأننا نستخدم ثلاث عمليات فقط لأي رقم `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+
2. يعض المحركات تدعم تحسين "tail call": أذا كان النداء المتكرر هو الأخير في الدالة (مثلما في`sumTo` ) إذا فالدالة الخارجية لن تحتاج إلي مواصلة التنفيذ وبالتالي فإن المحرك لا يحتاج إلي تذكر سياق التنفيذ. ذلك يزبل العبء عن الذاكرة لذلك العد إلي `sumTo(100000)` ممكناً. لكن محرك جافاسكريبت لا يدعم هذا التحسين أو المعظم لا يدعم, لذلك سيكون هناك خطأ: لقد تخطيت الحجم الأقصي لكومة سياق التنفيذ.

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

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

33
---
44

5-
# Sum all numbers till the given one
5+
# أجمع كل الأرقام إلي الرقم المُعطى
6+
7+
أكتب دالة `sumTo(n)` لحساب مجموع الارقام هكذا numbers `1 + 2 + ... + n`.
68

79
Write a function `sumTo(n)` that calculates the sum of numbers `1 + 2 + ... + n`.
810

9-
For instance:
11+
مثلاً:
1012

1113
```js no-beautify
1214
sumTo(1) = 1
@@ -17,20 +19,20 @@ sumTo(4) = 4 + 3 + 2 + 1 = 10
1719
sumTo(100) = 100 + 99 + ... + 2 + 1 = 5050
1820
```
1921

20-
Make 3 solution variants:
22+
أستخدم ثلاث طرق مختلفة:
2123

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.
24+
1. استخدم حلقة `for`.
25+
2. استخدم التكرار (مساعدة: `sumTo(n) = n + sumTo(n-1)` for `n > 1`)
26+
3. استخدم [المتتالية العددية](https://en.wikipedia.org/wiki/Arithmetic_progression).
2527

26-
An example of the result:
28+
مثال علي الناتج:
2729

2830
```js
2931
function sumTo(n) { /*... your code ... */ }
3032

3133
alert( sumTo(100) ); // 5050
3234
```
3335

34-
P.S. Which solution variant is the fastest? The slowest? Why?
36+
1. ما الحل الاسرع؟ وما الابطأ؟ ولماذا؟
3537

36-
P.P.S. Can we use recursion to count `sumTo(100000)`?
38+
2. نستطيع إستخدام التكرار للعد `sumTo(100000)`?

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
By definition, a factorial is `n!` can be written as `n * (n-1)!`.
21

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`.
2+
3+
الحل يكمن في التعريف `n!` يساوي `n * (n-1)`.
4+
5+
6+
بطريقة أخري, ناتج `factorial(n)` يمكن أن نحسبه علي هذه الطريقة `n` مضروب في ناتج `factorial(n-1)`. ومناداة `n-1` يمكن أن تنادي نفسها بتكرار أصغر فأصغر حتي نصل إلي`1`
47

58
```js run
69
function factorial(n) {
@@ -10,7 +13,7 @@ function factorial(n) {
1013
alert( factorial(5) ); // 120
1114
```
1215

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:
16+
الاساس التكراري هنا هو `1` يمكن أيضاً ان يكون `0` ولكن هذا لا يهم هذا يعطينا مناداة إضافية فقط:
1417

1518
```js run
1619
function factorial(n) {

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

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,20 @@ 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://en.wikipedia.org/wiki/Factorial) هو عدد طبيعي يعتبر حاصل ضرب الرقم في نفس الرقم - 1 ثم في نفسه - 2 وهكذا حتي نصل إلي 1.
8+
9+
مضروب العدد `n` يكتب رياضياً علي هذا الشكل and so on till `1`. The factorial of `n` is denoted as `n!`
10+
11+
يمكننا أن نعرفها بهذه الطريقة:
812

9-
We can write a definition of factorial like this:
1013

1114
```js
1215
n! = n * (n - 1) * (n - 2) * ...*1
1316
```
1417

15-
Values of factorials for different `n`:
18+
قيم مضروب أرقام مختلفة : للـ `n`
1619

1720
```js
1821
1! = 1
@@ -22,10 +25,12 @@ Values of factorials for different `n`:
2225
5! = 5 * 4 * 3 * 2 * 1 = 120
2326
```
2427

25-
The task is to write a function `factorial(n)` that calculates `n!` using recursive calls.
28+
المهمة هي أن تكتب دالة `factorial(n)` التي تقوم بحساب `n!` بإستخدام الداءات المتكررة.
2629

2730
```js
2831
alert( factorial(5) ); // 120
2932
```
3033

31-
P.S. Hint: `n!` can be written as `n * (n-1)!` For instance: `3! = 3*2! = 3*2*1! = 6`
34+
مساعدة: `n!` يمكن كتابته علي هذا الشكل `n * (n-1)!`
35+
مثلاً: `3! = 3*2! = 3*2*1! = 6`
36+

1-js/06-advanced-functions/01-recursion/03-fibonacci-numbers/solution.md

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
The first solution we could try here is the recursive one.
21

3-
Fibonacci numbers are recursive by definition:
2+
الحل الأول الذي مكن تجربته هنا هو الحل المتكرر.
3+
4+
أعداد فيبوناتشي متكررة وذلك واضح من التعريف:
5+
46

57
```js run
68
function fib(n) {
@@ -12,36 +14,37 @@ alert( fib(7) ); // 13
1214
// fib(77); // will be extremely slow!
1315
```
1416

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.
17+
لكن القيم الكبيرة من الـ `n` سيكون بطئ جداً مثلاً `fib(77)` يمكن أن تعطل المحركلمد من الزمن
1618

17-
That's because the function makes too many subcalls. The same values are re-evaluated again and again.
19+
ذلك لأن الدالة تحتوي علي منادايات كثيرة جداً داخلها لنفسها. نفس القيم تحسب مراتٍ كثيرة.
1820

19-
For instance, let's see a piece of calculations for `fib(5)`:
21+
مثلاً لنري قطعة من حساب `fib(5)`:
2022

2123
```js no-beautify
2224
...
2325
fib(5) = fib(4) + fib(3)
2426
fib(4) = fib(3) + fib(2)
2527
...
2628
```
29+
`fib(5)` و `fib(4)` كلاهما يحتاج لحساب `fib(3)` إذن هذا الدالة سوف تنادي مراتان ليس لهما علاقة ببعضهما.
2730

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.
29-
30-
Here's the full recursion tree:
31+
ها هي صورة كاملة لشجرة التكرار:
3132

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

34-
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`.
35+
واضح هنا أن `fib(3)` تمت مناداتها مرتين و `fib(2)` سيتم مناداتها وتنفيذها ثلاث مرات. لذلك سيكون عدد الدوال التي تم تنفيذها سيكون هائل جداً حتي إذا كان `n=77`.
36+
37+
يمكننا تحسين هذا عن طريق تذكر القيم التي تم حسابها من قبل: مثلاإذا وجدنا `fib(3)` تم حسابها من قبل نأتي بقيمتها فوراً ولا نقوم بتنفيذها مرة أخري
3538

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.
39+
ذلك يضع أمامنا خيار أخر وهو أن نتخلي عن التكرار واستخدام طريقة حل مبنية علي الـ Array مختلفة تماماً
3740

38-
Another variant would be to give up recursion and use a totally different loop-based algorithm.
41+
بدلاً من أن نذهب من `n` أسفل للقيم الأقل, يمكن أن نصنع حلقة تبدأ من `1` و `2`, ثم نأتي بـ `fib(3)` بأعتبار أن ناتجها هو مجموعهم, ثم `fib(4)` بأعتبار أن ناتجها مجموع القيماتان السابقان ثم `fib(5)` تذهب لأعلي ثم أعلي حتي تصل إلي القيمة المطلوبة. كل ما نحتاج تذكره هو الرقمين السابقين.
3942

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.
4143

42-
Here are the steps of the new algorithm in details.
44+
هنا سنشرح الخطوات للخوارزمية الجديدة بالتفصيل.
45+
46+
في البداية:
4347

44-
The start:
4548

4649
```js
4750
// a = fib(1), b = fib(2), these values are by definition 1
@@ -55,10 +58,10 @@ a b c
5558
1, 1, 2
5659
*/
5760
```
61+
الأن نحن نريد الحصول علي `fib(4) = fib(2) + fib(3)`.
5862

59-
Now we want to get `fib(4) = fib(2) + fib(3)`.
63+
الأن نحتاج إلي تبديل المتغيرات `a,b` سيصبحوا `fib(2),fib(3)` و `c` سيكون مجموعهم :
6064

61-
Let's shift the variables: `a,b` will get `fib(2),fib(3)`, and `c` will get their sum:
6265

6366
```js no-beautify
6467
a = b; // now a = fib(2)
@@ -71,7 +74,8 @@ c = a + b; // c = fib(4)
7174
*/
7275
```
7376

74-
The next step gives another sequence number:
77+
الخطوة التالية تعطينا تسلسل أخر للأرقام:
78+
7579

7680
```js no-beautify
7781
a = b; // now a = fib(3)
@@ -84,9 +88,10 @@ c = a + b; // c = fib(5)
8488
*/
8589
```
8690

87-
...And so on until we get the needed value. That's much faster than recursion and involves no duplicate computations.
91+
وهكذا وهكذا حتي نحصل علي القيمة المطلوبة. هذا أسرع بكثيير ويمنع حساب شئ تم حسابه مسبقاً.
92+
8893

89-
The full code:
94+
الكود كاملاً:
9095

9196
```js run
9297
function fib(n) {
@@ -104,7 +109,7 @@ alert( fib(3) ); // 2
104109
alert( fib(7) ); // 13
105110
alert( fib(77) ); // 5527939700884757
106111
```
112+
الحلقة تبدأ من `i=3`, لأننا نعرف قيمة العددين الأولين `a=1`, `b=1`.
107113

108-
The loop starts with `i=3`, because the first and the second sequence values are hard-coded into variables `a=1`, `b=1`.
109114

110-
The approach is called [dynamic programming bottom-up](https://en.wikipedia.org/wiki/Dynamic_programming).
115+
هذا الحل يسمي [البرمجة الديناميكية](https://en.wikipedia.org/wiki/Dynamic_programming).

1-js/06-advanced-functions/01-recursion/03-fibonacci-numbers/task.md

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

33
---
44

5-
# Fibonacci numbers
5+
# أعداد فيبوناتشي
66

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://en.wikipedia.org/wiki/Fibonacci_number) لها قانون <code>F<sub>n</sub> = F<sub>n-1</sub> + F<sub>n-2</sub></code>. أو بمعني أخر الرقم القادم يساوي مجموع الرقمين الذان يسبقانه
88

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...`.
1010

11-
Fibonacci numbers are related to the [Golden ratio](https://en.wikipedia.org/wiki/Golden_ratio) and many natural phenomena around us.
11+
أعداد فيبوناتشي مرتبطة بالـ [نسبة الذهبية ](https://en.wikipedia.org/wiki/Golden_ratio) وكثير من الظواهر الطبيعية.
1212

13-
Write a function `fib(n)` that returns the `n-th` Fibonacci number.
13+
أكتب دالة `fib(n)` تُعطيك `n-th` العدد الموجود في هذا الترتيب
1414

15-
An example of work:
15+
مثلاً:
1616

1717
```js
1818
function fib(n) { /* your code */ }
@@ -22,4 +22,5 @@ alert(fib(7)); // 13
2222
alert(fib(77)); // 5527939700884757
2323
```
2424

25-
P.S. The function should be fast. The call to `fib(77)` should take no more than a fraction of a second.
25+
ملحوظة: الدالة يجب أن تكون سريعة. نداء `fib(77)` يجب ألا يأخذ أكثر من أجزاء من الثانية
26+

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

Lines changed: 15 additions & 10 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 = {
@@ -29,8 +29,8 @@ function printList(list) {
2929

3030
printList(list);
3131
```
32+
يرجي ملاحظة أننا نستخدم المتغير المؤقت `tmp` للمرور خلال القائمة. من الناحية الفنية, يمكن أن نستخدم عامل الدالة `list`:
3233

33-
Please note that we use a temporary variable `tmp` to walk over the list. Technically, we could use a function parameter `list` instead:
3434

3535
```js
3636
function printList(list) {
@@ -43,15 +43,20 @@ 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+
لكن هذا لن يكون محبذاً في المستقبل لأنه بسبب ما من الممكن أن نمد الدالة لفعل شئ أخر للقائمة.
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` سنخسر هذه الميزة.
49+
50+
بمناسبة الحديث عن التسمية الجيدة للمتغيرات, `list` تعتبر الـ القائمة نفسها. بمعني أدق العنصر الأول فيها. وهو يجب أن يبقي هكذا.
51+
52+
علي صعيد أخر, دور `tmp` يهتم فقط بالانتقال بين عناصر القائمة, مثل `i` الموجود في حلقة `for`
4953

5054
From the other side, the role of `tmp` is exclusively a list traversal, like `i` in the `for` loop.
5155

52-
# Recursive solution
56+
# الحل التكراري
57+
58+
الحل التكراري للدالة `printList(list)` يتبع منطق بسيط لطباعة القائمة: يجب طباعة العنصر الحالي `list` ثم إعادة الموضوع للباقي `list.next` حتي تنتهي القائمة :
5359

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`:
5560

5661
```js run
5762
let list = {
@@ -81,8 +86,8 @@ function printList(list) {
8186
printList(list);
8287
```
8388

84-
Now what's better?
89+
الأن من هو الأفضل؟
8590

86-
Technically, the loop is more effective. These two variants do the same, but the loop does not spend resources for nested function calls.
91+
عملياً الحلقة أكثر كفاءة بالرغم من أنهم يقومون بنفس المهمة, لكن الحلقة لا تستطيع عمل أكثر من نداء متداخل.
8792

88-
From the other side, the recursive variant is shorter and sometimes easier to understand.
93+
علي الجانب الأخر التكرار يعتبر أسهل للفهم وأقصر

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

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

33
---
44

5-
# Output a single-linked list
5+
# طباعة قائمة متصلة فردية
6+
7+
هذه هي القائمة المتصلة كما ذكرناها في هذا الفصل <info:recursion>:
68

7-
Let's say we have a single-linked list (as described in the chapter <info:recursion>):
89

910
```js
1011
let list = {
@@ -21,9 +22,10 @@ let list = {
2122
}
2223
};
2324
```
25+
إكتب دالة `printList(list)` التي تقوم بطباعة القائمة واحداً تلو الأخر.
2426

25-
Write a function `printList(list)` that outputs list items one-by-one.
26-
27-
Make two variants of the solution: using a loop and using recursion.
27+
قم بحلها بطريقتين:
28+
1. مرة بإستخدام الحلقة:
29+
2. مرة بإستخدام التكرار:
2830

29-
What's better: with recursion or without it?
31+
ماهو الأفضل: بالتكرار أم بدون التكرار؟

0 commit comments

Comments
 (0)