Javascript Recursion for Beginners (super simple)

JS
S
JavaScript

Super simple explanation of how recursive functions work in JS. So basically what we are doing with a recursive function call is: Trivia: Reduce the list at each step until we get to an empty list; Trivia: Reduce the number at each step until we get to 0; Trivia: Reduce the string at each step until we get to ''; Computation: On the way return the value what you want to add, append, subtract, multiply with the result

1/* 
2  offuscateString('test');
3  offuscateString('shoes');
4  offuscateString('shoes');
5  offuscateString('shoes');
6  offuscateString('shoes');
7  // result = test shoes shoes shoes shoes
8*/
9let counter = 5;
10const offuscateStringDummy = (sourceStr) => {
11  if (counter === 0) {
12    return '';
13  }
14  counter--;
15  return sourceStr + ' ' + offuscateStringDummy('shoes');
16}
17
18const off = offuscateStringDummy('test');
19console.log(off)
20
21
22// ==============================================================================================================================
23/* Second Example
24  Ok, now we are running this order:
25  offuscateStringLessDummy('test');
26  // YUP WE ARE CALLING SHOES WITHOUT THE LAST CHAR, COUNTER === 4
27  offuscateStringLessDummy('shoe');
28  offuscateStringLessDummy('sho');
29  offuscateStringLessDummy('sh');
30  offuscateStringLessDummy('s');
31*/
32let counter = 5;
33const offuscateStringLessDummy = (sourceStr) => {
34  if (counter === 0) {
35    return '';
36  }
37  counter--;
38  return sourceStr + ' ' + offuscateStringLessDummy('shoes'.slice(0, counter));
39}
40
41const off = offuscateStringLessDummy('test');
42console.log(off)
43
44// ==============================================================================================================================
45/*
46  Smart
47  Now we are removing last char of the str on every call and using the incrementally smaller string as our counter, like so:
48  offuscateStringSmart('test')
49  offuscateStringSmart('tes')
50  offuscateStringSmart('te')
51  offuscateStringSmart('t')
52
53  result: test tes te t
54
55*/
56const offuscateStringSmart = (sourceStr) => {
57  if (sourceStr.length === 0) {
58    return '';
59  }
60  return sourceStr + ' ' + offuscateStringSmart(sourceStr.slice(0, sourceStr.length - 1));
61}
62
63const off = offuscateStringSmart('test');
64console.log(off)
65
66
67// ==============================================================================================================================
68/*
69  OK, now that the basics are covered:
70  WE WILL REVERT THE STRING, BY CUTTING IT DOWN FROM THE END ON EACH ITERATION
71  AND GLUING THE LAST CHARACTER
72  offuscateStringSmarter('t')
73  offuscateStringSmarter('s')
74  offuscateStringSmarter('e')
75  offuscateStringSmarter('t')
76
77  REMEMBER THE PROCESSING (BOTTOM OF STACK UP, SO THE LAST ITEM ON THE CALL STACK IS "offuscateStringSmarter('t)")
78  RECURSION STOPS THERE AS WILL HIT 0
79  't' + 's' + 'e' + 't'
80
81  // result tset
82*/
83const offuscateStringSmarter = (sourceStr) => {
84  console.log('>', sourceStr)
85  if (sourceStr.length === 0) {
86    return '';
87  }
88  const lastChar = sourceStr.charAt(sourceStr.length - 1);
89  const withouLastChar = sourceStr.slice(0, sourceStr.length - 1);
90  return lastChar + offuscateStringSmarter(withouLastChar);
91}
92
93const off = offuscateStringSmarter('test');
94console.log('result', off)
95
96
97// ==============================================================================================================================
98/*
99  OK, To finalize, lets step it up a bit, like so:
100  SEQUENCE OF CALLS
101  offuscateStringGenius('test')
102  offuscateStringGenius('tes')
103  offuscateStringGenius('te')
104  offuscateStringGenius('t')
105
106  BUILD UP RESULT (DONT FORGET THAT WE ARE RETURNING THE lastCharHashed + '')
107  '' HUN?
108  YES, DO NOT FORGET THAT '' CAME FROM OUR STOP CONDITION
109  offuscateStringGenius('t') 74 ['t']
110  offuscateStringGenius('te') 65 ['e']
111  offuscateStringGenius('tes') 73 ['s']
112  offuscateStringGenius('test') 74 ['t']
113*/
114const offuscateStringGenius = (sourceStr) => {
115  console.log('>', sourceStr)
116  if (sourceStr.length === 0) {
117    return '';
118  }
119  const lastChar = sourceStr.charAt(sourceStr.length - 1);
120  const withouLastChar = sourceStr.slice(0, sourceStr.length - 1);
121  const lastCharHashed = lastChar.charCodeAt(0).toString(16)
122  return lastCharHashed + offuscateStringGenius(withouLastChar);
123}
124
125const off = offuscateStringGenius('test');
126console.log('result', off) //74736574
127
128// IF YOU THING A BIT ON OUR CASE, IT'S KIND OF A REDUCTION, WE HAVE REDUCED THE STRING FROM 5 CHARACTERS TO AN EMPTY STRING
129
130// ==============================================================================================================================
131// More simple examples
132/*
133  multiplyWithRecursion(2,4) // 2
134  multiplyWithRecursion(2,3) // 2
135  multiplyWithRecursion(2,2) // 2
136  multiplyWithRecursion(2,1) // 2
137  // Unwind
138  2 + 2 + 2 + 2 + 0
139*/
140const multiplyWithRecursion = (x,y) => {
141  // Stop condition
142  if(y === 0){
143    return 0;
144  }
145  y--;
146  return x + multiplyWithRecursion(x, y);
147}
148const res = multiplyWithRecursion(2,4);
149console.log('res', res);
150
151
152
153/* Recursion on Lists
154Trivia: Reduce the list at each step until we get to an empty list;
155Remember: We are adding all sumAllNumbersInTheList()  return values, like so:
156  sumAllNumbersInTheList([1,2,3,4,5]); // 1
157  sumAllNumbersInTheList([2,3,4,5]); // 2
158  sumAllNumbersInTheList([3,4,5]); // 3
159  sumAllNumbersInTheList([4,5]); // 4
160  sumAllNumbersInTheList([5]); //5
161  sumAllNumbersInTheList([]); //0
162
163  UNWIND:
164  1+2+3+4+5+0 = 15
165    sumAllNumbersInTheList([1,2,3,4,5])
166    1 + sumAllNumbersInTheList([2,3,4,5])
167    1 + 2 + sumAllNumbersInTheList([3,4,5])
168    1 + 2 + 3 + sumAllNumbersInTheList([4,5])
169    1 + 2 + 3 + 4 sumAllNumbersInTheList([5])
170    1 + 2 + 3 + 4 + 5 sumAllNumbersInTheList([])
171    1 + 2 + 3 + 4 + 5 + 0
172*/
173const sumAllNumbersInTheList = (list) => {
174  if(list.length === 0) {
175    return 0; // we are suming, remember?
176  } else {
177    return list.shift() + sumAllNumbersInTheList(list); // remember: shift() reduces the array by 1
178  }
179};
180
181const res = sumAllNumbersInTheList([1,2,3,4,5]);
182console.log('res', res); // 15
183
184
185// ==============================================================================================================================
186/*
187  removeSpecificElement(x, [1,2,3,4,5]) // [1]
188  removeSpecificElement(x, [2,3,4,5]) // [2]
189  removeSpecificElement(x, [3,4,5]) // [3]
190  removeSpecificElement(x, [4,5]) // [5]
191
192  UNWIND
193  concat
194  [1][2][3][5]
195*/
196
197const removeSpecificElement = (itemToRemove, list) => {
198  console.log('process', itemToRemove, list)
199  const indexOfItemToRemove = list.indexOf(itemToRemove);
200  if(indexOfItemToRemove === 0) {
201    // Finally the item to remove is on position zero, exit the recursion
202    list.shift();
203    return list;
204  } else {
205    // reduce the list but keep element
206    const shiftedEl = list.shift();
207    return [shiftedEl].concat(removeSpecificElement(itemToRemove, list));
208  }
209};
210
211const res1 = removeSpecificElement(4, [1,2,3,4,5]);
212console.log(res1);

Created on 2/19/2019