4 | Recursion Test Suite
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/lib/testSupport.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | mocha.setup({ui: 'bdd'});
5 | window.expect = chai.expect;
6 |
7 | window.onload = function() {
8 | window.mochaPhantomJS ? mochaPhantomJS.run() : mocha.run();
9 | };
10 |
11 |
12 | // Disabling native methods is dangerous, we should spy on them instead
13 | before(function() {
14 | sinon.spy(Array.prototype,'map');
15 | sinon.spy(Array.prototype,'sort');
16 | sinon.spy(Array.prototype,'reverse');
17 | sinon.spy(Object,'assign');
18 | sinon.spy(JSON,'stringify');
19 | sinon.spy(JSON,'parse');
20 | window.analyze = o => {
21 | let c = 0;
22 | for (let k in o) {
23 | typeof o[k] === 'object' && (c += analyze(o[k]));
24 | c++;
25 | }
26 | return c;
27 | };
28 | });
29 |
30 | afterEach(function() {
31 | Array.prototype.map.reset();
32 | Array.prototype.sort.reset();
33 | Array.prototype.reverse.reset();
34 | Object.assign.reset();
35 | JSON.stringify.reset();
36 | JSON.parse.reset();
37 | });
38 |
39 | after(function() {
40 | Array.prototype.map.restore();
41 | Array.prototype.sort.restore();
42 | Array.prototype.reverse.restore();
43 | Object.assign.restore();
44 | JSON.stringify.restore();
45 | JSON.parse.restore();
46 | delete window.analyze;
47 | });
48 |
49 | }());
50 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Recursion Prompts
2 |
3 | ### **What is this?**
4 | This is a repository of toy problems to be solved using recursion and JavaScript. While the concept of recursion may not be difficult to grasp, the only way to improve at thinking recursively is by practice. If you need practice, then maybe this repo is for you.
5 |
6 | ### **A few guidelines:**
7 | - Please refrain from sharing solutions. As crazy as it sounds, giving someone the answer doesn't help them. Instead, give them a question that encourages them to think differently.
8 |
9 | > **Q:** Why does my function keep exceeding the call stack?
10 |
11 | > **A:** What's your base case?
12 |
13 | - Don't be afraid to pseudocode your algorithm before writing actual code.
14 |
15 | > Pseudocode helps you focus on the algorithm instead of getting distracted by syntax.
16 |
17 | - This repo requires each function call itself recursively and pays no attention to whether inner recursive functions are defined and called.
18 |
19 | > While both are valid uses of recursion, there are important lessons to learn by following the method this repo enforces. Defining inner functions and calling them recursively relies on side effects, while following the more pure approach requires an understanding of how values are passed through the call stack.
20 |
21 | - This repo restricts expanding the number of parameters a function accepts.
22 |
23 | > Expanding the number of parameters is a valid approach, but has been restricted here to emphasize certain lessons while learning recursion.
24 |
25 | - An attempt was made to order prompts by difficulty, but they don't have to be solved in any particular order.
26 | - Feel free to make pull requests or open issues regarding bugs or suggestions.
27 | - **`Watch`**, **`Star`**, and **`Fork`** this repo. You know you want to.
28 |
29 | ### **How to use this repo:**
30 | 1. Fork this repo and clone it to your local machine
31 | 2. Open `SpecRunner.html` in your web browser
32 | 3. Code your solutions in `recursion.js`
33 | 4. Review the tests in `spec/part1.js` and `spec/part2.js` as necessary
34 | 5. Save your work and refresh your browser to check for passing/failing tests
35 |
36 | ---
37 | ### What is recursion?
38 | > Recursion is when a function calls itself until it doesn't. --not helpful person
39 |
40 | Is it a true definition? Mostly. Recursion is when a function calls itself. A recursive function can call itself forever, but that's generally not preferred. It's often a good idea to include a condition in the function definition that allows it to stop calling itself. This condition is referred to as a **_base_** case. As a general rule, recursion shouldn't be utilized without an accompanying base case unless an infinite operation is desired. This leaves us with two fundamental conditions every recursive function should include:
41 | - A **`base`** case
42 | - A **`recursive`** case
43 |
44 | _What does this all mean?_ Let's consider a silly example:
45 | ```sh
46 | function stepsToZero(n) {
47 | if (!n === 0) { /* base case */
48 | console.log('Reached zero');
49 | return;
50 | } else { /* recursive case */
51 | console.log(n + ' is not zero');
52 | return stepsToZero(n-1);
53 | }
54 | }
55 | ```
56 | This function doesn't do anything meaningful, but hopefully it demonstrates the fundamental idea behind recursion. Simply put, recursion provides us a looping or repeating mechanism. It repeats an operation until a `base` condition is met. Let's step through an invocation of the above function to see how it evaluates.
57 |
58 | 1. Invoke `stepsToZero(n)` where `n` is the number `2`
59 | 2. Is 2 zero?
60 | 3. No, print message to console that 2 is not zero
61 | 4. Invoke `stepsToZero(n-1)` where `n-1` evaluates to `1`
62 |
63 | > Every recursive call adds a new invocation to the stack on top of the previous invocation
64 |
65 | 5. Is 1 zero?
66 | 6. No, print message that 1 is not zero
67 | 7. Invoke `stepsToZero(n-1)` where `n-1` evaluates to `0`
68 | 8. Is 0 zero?
69 | 9. Yes, print message that reached zero
70 | 10. Return out of the current invocation
71 | 6. Resume the invocation from step 4 where it left off (in-between steps 6 and 7)
72 | 6. Return out of the invocation from step 4
73 | 12. Resume the initial invocation from step 1 where it left off (in-between steps 3 and 4)
74 | 12. Return out of the initial invocation
75 |
76 | Due to the way the execution stack operates, it's as if each function invocation pauses in time when a recursive call is made. The function that pauses before a recursive call will resume once the recursive call completes. If you've seen the movie [Inception], this model may sound reminiscent to when the characters enter a person's dreams and time slowed. The difference is time doesn't actually slow with recursive invocations; rather, it's a matter of order of operations. If a new invocation enters the execution stack, that invocation must complete before the previous can continue and complete.
77 |
78 |
79 | ### Why use recursion?
80 | Recursion can be elegant, but it can also be dangerous. It some cases, recursion feels like a more natural and readable solution; in others, it ends up being contrived. In most cases, recursion can be avoided entirely and sometimes should in order to minimize the possibility of exceeding the call stack and crashing your app. But keep in mind that code readability is important. If a recursive solution reads more naturally, then it may be the best solution for the given problem.
81 |
82 | Recursion isn't unique to any one programming language. As a software engineer, you _will_ encounter recursion and it's important to understand what's happening and how to work with it. It's also important to understand why someone might use it. Recursion is often used when the depth of a thing is unknown or every element of a thing needs to be touched. For example, you might use recursion if you want to find all DOM elements with a specific class name. You may not know how deep the DOM goes and need to touch every element so that none are missed. The same can be said for traversing any structure where all possible paths need to be considered and investigated.
83 |
84 |
85 | ### Divide and Conquer
86 | Recursion is often used in _divide and conquer_ algorithms where problems can be divided into similar subproblems and conquered individually. Consider traversing a tree structure. Each branch may have its own "children" branches. Every branch is essentually just another tree which means, as long as child trees are found, we can recurse on each child.
87 |
88 | [inception]:
89 |
--------------------------------------------------------------------------------
/lib/css/mocha.css:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 |
3 | body {
4 | margin:0;
5 | }
6 |
7 | #mocha {
8 | font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
9 | margin: 60px 50px;
10 | }
11 |
12 | #mocha ul,
13 | #mocha li {
14 | margin: 0;
15 | padding: 0;
16 | }
17 |
18 | #mocha ul {
19 | list-style: none;
20 | }
21 |
22 | #mocha h1,
23 | #mocha h2 {
24 | margin: 0;
25 | }
26 |
27 | #mocha h1 {
28 | margin-top: 15px;
29 | font-size: 1em;
30 | font-weight: 200;
31 | }
32 |
33 | #mocha h1 a {
34 | text-decoration: none;
35 | color: inherit;
36 | }
37 |
38 | #mocha h1 a:hover {
39 | text-decoration: underline;
40 | }
41 |
42 | #mocha .suite .suite h1 {
43 | margin-top: 0;
44 | font-size: .8em;
45 | }
46 |
47 | #mocha .hidden {
48 | display: none;
49 | }
50 |
51 | #mocha h2 {
52 | font-size: 12px;
53 | font-weight: normal;
54 | cursor: pointer;
55 | }
56 |
57 | #mocha .suite {
58 | margin-left: 15px;
59 | }
60 |
61 | #mocha .test {
62 | margin-left: 15px;
63 | overflow: hidden;
64 | }
65 |
66 | #mocha .test.pending:hover h2::after {
67 | content: '(pending)';
68 | font-family: arial, sans-serif;
69 | }
70 |
71 | #mocha .test.pass.medium .duration {
72 | background: #c09853;
73 | }
74 |
75 | #mocha .test.pass.slow .duration {
76 | background: #b94a48;
77 | }
78 |
79 | #mocha .test.pass::before {
80 | content: '✓';
81 | font-size: 12px;
82 | display: block;
83 | float: left;
84 | margin-right: 5px;
85 | color: #00d6b2;
86 | }
87 |
88 | #mocha .test.pass .duration {
89 | font-size: 9px;
90 | margin-left: 5px;
91 | padding: 2px 5px;
92 | color: #fff;
93 | -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
94 | -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
95 | box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
96 | -webkit-border-radius: 5px;
97 | -moz-border-radius: 5px;
98 | -ms-border-radius: 5px;
99 | -o-border-radius: 5px;
100 | border-radius: 5px;
101 | }
102 |
103 | #mocha .test.pass.fast .duration {
104 | display: none;
105 | }
106 |
107 | #mocha .test.pending {
108 | color: #0b97c4;
109 | }
110 |
111 | #mocha .test.pending::before {
112 | content: '◦';
113 | color: #0b97c4;
114 | }
115 |
116 | #mocha .test.fail {
117 | color: #c00;
118 | }
119 |
120 | #mocha .test.fail pre {
121 | color: black;
122 | }
123 |
124 | #mocha .test.fail::before {
125 | content: '✖';
126 | font-size: 12px;
127 | display: block;
128 | float: left;
129 | margin-right: 5px;
130 | color: #c00;
131 | }
132 |
133 | #mocha .test pre.error {
134 | color: #c00;
135 | max-height: 300px;
136 | overflow: auto;
137 | }
138 |
139 | #mocha .test .html-error {
140 | overflow: auto;
141 | color: black;
142 | line-height: 1.5;
143 | display: block;
144 | float: left;
145 | clear: left;
146 | font: 12px/1.5 monaco, monospace;
147 | margin: 5px;
148 | padding: 15px;
149 | border: 1px solid #eee;
150 | max-width: 85%; /*(1)*/
151 | max-width: -webkit-calc(100% - 42px);
152 | max-width: -moz-calc(100% - 42px);
153 | max-width: calc(100% - 42px); /*(2)*/
154 | max-height: 300px;
155 | word-wrap: break-word;
156 | border-bottom-color: #ddd;
157 | -webkit-box-shadow: 0 1px 3px #eee;
158 | -moz-box-shadow: 0 1px 3px #eee;
159 | box-shadow: 0 1px 3px #eee;
160 | -webkit-border-radius: 3px;
161 | -moz-border-radius: 3px;
162 | border-radius: 3px;
163 | }
164 |
165 | #mocha .test .html-error pre.error {
166 | border: none;
167 | -webkit-border-radius: 0;
168 | -moz-border-radius: 0;
169 | border-radius: 0;
170 | -webkit-box-shadow: 0;
171 | -moz-box-shadow: 0;
172 | box-shadow: 0;
173 | padding: 0;
174 | margin: 0;
175 | margin-top: 18px;
176 | max-height: none;
177 | }
178 |
179 | /**
180 | * (1): approximate for browsers not supporting calc
181 | * (2): 42 = 2*15 + 2*10 + 2*1 (padding + margin + border)
182 | * ^^ seriously
183 | */
184 | #mocha .test pre {
185 | display: block;
186 | float: left;
187 | clear: left;
188 | font: 12px/1.5 monaco, monospace;
189 | margin: 5px;
190 | padding: 15px;
191 | border: 1px solid #eee;
192 | max-width: 85%; /*(1)*/
193 | max-width: -webkit-calc(100% - 42px);
194 | max-width: -moz-calc(100% - 42px);
195 | max-width: calc(100% - 42px); /*(2)*/
196 | word-wrap: break-word;
197 | border-bottom-color: #ddd;
198 | -webkit-box-shadow: 0 1px 3px #eee;
199 | -moz-box-shadow: 0 1px 3px #eee;
200 | box-shadow: 0 1px 3px #eee;
201 | -webkit-border-radius: 3px;
202 | -moz-border-radius: 3px;
203 | border-radius: 3px;
204 | }
205 |
206 | #mocha .test h2 {
207 | position: relative;
208 | }
209 |
210 | #mocha .test a.replay {
211 | position: absolute;
212 | top: 3px;
213 | right: 0;
214 | text-decoration: none;
215 | vertical-align: middle;
216 | display: block;
217 | width: 15px;
218 | height: 15px;
219 | line-height: 15px;
220 | text-align: center;
221 | background: #eee;
222 | font-size: 15px;
223 | -webkit-border-radius: 15px;
224 | -moz-border-radius: 15px;
225 | border-radius: 15px;
226 | -webkit-transition:opacity 200ms;
227 | -moz-transition:opacity 200ms;
228 | -o-transition:opacity 200ms;
229 | transition: opacity 200ms;
230 | opacity: 0.3;
231 | color: #888;
232 | }
233 |
234 | #mocha .test:hover a.replay {
235 | opacity: 1;
236 | }
237 |
238 | #mocha-report.pass .test.fail {
239 | display: none;
240 | }
241 |
242 | #mocha-report.fail .test.pass {
243 | display: none;
244 | }
245 |
246 | #mocha-report.pending .test.pass,
247 | #mocha-report.pending .test.fail {
248 | display: none;
249 | }
250 | #mocha-report.pending .test.pass.pending {
251 | display: block;
252 | }
253 |
254 | #mocha-error {
255 | color: #c00;
256 | font-size: 1.5em;
257 | font-weight: 100;
258 | letter-spacing: 1px;
259 | }
260 |
261 | #mocha-stats {
262 | position: fixed;
263 | top: 15px;
264 | right: 10px;
265 | font-size: 12px;
266 | margin: 0;
267 | color: #888;
268 | z-index: 1;
269 | }
270 |
271 | #mocha-stats .progress {
272 | float: right;
273 | padding-top: 0;
274 |
275 | /**
276 | * Set safe initial values, so mochas .progress does not inherit these
277 | * properties from Bootstrap .progress (which causes .progress height to
278 | * equal line height set in Bootstrap).
279 | */
280 | height: auto;
281 | -webkit-box-shadow: none;
282 | -moz-box-shadow: none;
283 | box-shadow: none;
284 | background-color: initial;
285 | }
286 |
287 | #mocha-stats em {
288 | color: black;
289 | }
290 |
291 | #mocha-stats a {
292 | text-decoration: none;
293 | color: inherit;
294 | }
295 |
296 | #mocha-stats a:hover {
297 | border-bottom: 1px solid #eee;
298 | }
299 |
300 | #mocha-stats li {
301 | display: inline-block;
302 | margin: 0 5px;
303 | list-style: none;
304 | padding-top: 11px;
305 | }
306 |
307 | #mocha-stats canvas {
308 | width: 40px;
309 | height: 40px;
310 | }
311 |
312 | #mocha code .comment { color: #ddd; }
313 | #mocha code .init { color: #2f6fad; }
314 | #mocha code .string { color: #5890ad; }
315 | #mocha code .keyword { color: #8a6343; }
316 | #mocha code .number { color: #2f6fad; }
317 |
318 | @media screen and (max-device-width: 480px) {
319 | #mocha {
320 | margin: 60px 0px;
321 | }
322 |
323 | #mocha #stats {
324 | position: absolute;
325 | }
326 | }
327 |
--------------------------------------------------------------------------------
/src/recursion.js:
--------------------------------------------------------------------------------
1 | /* jshint esversion: 6 */
2 |
3 | // Solve the following prompts using recursion.
4 |
5 | // 1. Calculate the factorial of a number. The factorial of a non-negative integer n,
6 | // denoted by n!, is the product of all positive integers less than or equal to n.
7 | // Example: 5! = 5 x 4 x 3 x 2 x 1 = 120
8 | // factorial(5); // 120
9 | var factorial = function(n) {
10 | };
11 |
12 | // 2. Compute the sum of an array of integers.
13 | // sum([1,2,3,4,5,6]); // 21
14 | var sum = function(array) {
15 | };
16 |
17 | // 3. Sum all numbers in an array containing nested arrays.
18 | // arraySum([1,[2,3],[[4]],5]); // 15
19 | var arraySum = function(array) {
20 | };
21 |
22 | // 4. Check if a number is even.
23 | var isEven = function(n) {
24 | };
25 |
26 | // 5. Sum all integers below a given integer.
27 | // sumBelow(10); // 45
28 | // sumBelow(7); // 21
29 | var sumBelow = function(n) {
30 | };
31 |
32 | // 6. Get the integers within a range (x, y).
33 | // range(2,9); // [3,4,5,6,7,8]
34 | var range = function(x, y) {
35 | };
36 |
37 | // 7. Compute the exponent of a number.
38 | // The exponent of a number says how many times the base number is used as a factor.
39 | // 8^2 = 8 x 8 = 64. Here, 8 is the base and 2 is the exponent.
40 | // exponent(4,3); // 64
41 | // https://www.khanacademy.org/computing/computer-science/algorithms/recursive-algorithms/a/computing-powers-of-a-number
42 | var exponent = function(base, exp) {
43 | };
44 |
45 | // 8. Determine if a number is a power of two.
46 | // powerOfTwo(1); // true
47 | // powerOfTwo(16); // true
48 | // powerOfTwo(10); // false
49 | var powerOfTwo = function(n) {
50 | };
51 |
52 | // 9. Write a function that reverses a string.
53 | var reverse = function(string) {
54 | };
55 |
56 | // 10. Write a function that determines if a string is a palindrome.
57 | var palindrome = function(string) {
58 | };
59 |
60 | // 11. Write a function that returns the remainder of x divided by y without using the
61 | // modulo (%) operator.
62 | // modulo(5,2) // 1
63 | // modulo(17,5) // 2
64 | // modulo(22,6) // 4
65 | var modulo = function(x, y) {
66 | };
67 |
68 | // 12. Write a function that multiplies two numbers without using the * operator or
69 | // Math methods.
70 | var multiply = function(x, y) {
71 | };
72 |
73 | // 13. Write a function that divides two numbers without using the / operator or
74 | // Math methods.
75 | var divide = function(x, y) {
76 | };
77 |
78 | // 14. Find the greatest common divisor (gcd) of two positive numbers. The GCD of two
79 | // integers is the greatest integer that divides both x and y with no remainder.
80 | // gcd(4,36); // 4
81 | // http://www.cse.wustl.edu/~kjg/cse131/Notes/Recursion/recursion.html
82 | // https://www.khanacademy.org/computing/computer-science/cryptography/modarithmetic/a/the-euclidean-algorithm
83 | var gcd = function(x, y) {
84 | };
85 |
86 | // 15. Write a function that compares each character of two strings and returns true if
87 | // both are identical.
88 | // compareStr('house', 'houses') // false
89 | // compareStr('tomato', 'tomato') // true
90 | var compareStr = function(str1, str2) {
91 | };
92 |
93 | // 16. Write a function that accepts a string and creates an array where each letter
94 | // occupies an index of the array.
95 | var createArray = function(str) {
96 | };
97 |
98 | // 17. Reverse the order of an array
99 | var reverseArr = function(array) {
100 | };
101 |
102 | // 18. Create a new array with a given value and length.
103 | // buildList(0,5) // [0,0,0,0,0]
104 | // buildList(7,3) // [7,7,7]
105 | var buildList = function(value, length) {
106 | };
107 |
108 | // 19. Implement FizzBuzz. Given integer n, return an array of the string representations of 1 to n.
109 | // For multiples of three, output 'Fizz' instead of the number.
110 | // For multiples of five, output 'Buzz' instead of the number.
111 | // For numbers which are multiples of both three and five, output “FizzBuzz” instead of the number.
112 | // fizzBuzz(5) // ['1','2','Fizz','4','Buzz']
113 | var fizzBuzz = function(n) {
114 | };
115 |
116 | // 20. Count the occurence of a value in a list.
117 | // countOccurrence([2,7,4,4,1,4], 4) // 3
118 | // countOccurrence([2,'banana',4,4,1,'banana'], 'banana') // 2
119 | var countOccurrence = function(array, value) {
120 | };
121 |
122 | // 21. Write a recursive version of map.
123 | // rMap([1,2,3], timesTwo); // [2,4,6]
124 | var rMap = function(array, callback) {
125 | };
126 |
127 | // 22. Write a function that counts the number of times a key occurs in an object.
128 | // var obj = {'e':{'x':'y'},'t':{'r':{'e':'r'},'p':{'y':'r'}},'y':'e'};
129 | // countKeysInObj(obj, 'r') // 1
130 | // countKeysInObj(obj, 'e') // 2
131 | var countKeysInObj = function(obj, key) {
132 | };
133 |
134 | // 23. Write a function that counts the number of times a value occurs in an object.
135 | // var obj = {'e':{'x':'y'},'t':{'r':{'e':'r'},'p':{'y':'r'}},'y':'e'};
136 | // countValuesInObj(obj, 'r') // 2
137 | // countValuesInObj(obj, 'e') // 1
138 | var countValuesInObj = function(obj, value) {
139 | };
140 |
141 | // 24. Find all keys in an object (and nested objects) by a provided name and rename
142 | // them to a provided new name while preserving the value stored at that key.
143 | var replaceKeysInObj = function(obj, oldKey, newKey) {
144 | };
145 |
146 | // 25. Get the first n Fibonacci numbers. In the Fibonacci sequence, each subsequent
147 | // number is the sum of the previous two.
148 | // Example: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34.....
149 | // fibonacci(5); // [0,1,1,2,3,5]
150 | // Note: The 0 is not counted.
151 | var fibonacci = function(n) {
152 | };
153 |
154 | // 26. Return the Fibonacci number located at index n of the Fibonacci sequence.
155 | // [0,1,1,2,3,5,8,13,21]
156 | // nthFibo(5); // 5
157 | // nthFibo(7); // 13
158 | // nthFibo(3); // 2
159 | var nthFibo = function(n) {
160 | };
161 |
162 | // 27. Given an array of words, return a new array containing each word capitalized.
163 | // var words = ['i', 'am', 'learning', 'recursion'];
164 | // capitalizedWords(words); // ['I', 'AM', 'LEARNING', 'RECURSION']
165 | var capitalizeWords = function(array) {
166 | };
167 |
168 | // 28. Given an array of strings, capitalize the first letter of each index.
169 | // capitalizeFirst(['car','poop','banana']); // ['Car','Poop','Banana']
170 | var capitalizeFirst = function(array) {
171 | };
172 |
173 | // 29. Return the sum of all even numbers in an object containing nested objects.
174 | // var obj1 = {
175 | // a: 2,
176 | // b: {b: 2, bb: {b: 3, bb: {b: 2}}},
177 | // c: {c: {c: 2}, cc: 'ball', ccc: 5},
178 | // d: 1,
179 | // e: {e: {e: 2}, ee: 'car'}
180 | // };
181 | // nestedEvenSum(obj1); // 10
182 | var nestedEvenSum = function(obj) {
183 | };
184 |
185 | // 30. Flatten an array containing nested arrays.
186 | // flatten([1,[2],[3,[[4]]],5]); // [1,2,3,4,5]
187 | var flatten = function(array) {
188 | };
189 |
190 | // 31. Given a string, return an object containing tallies of each letter.
191 | // letterTally('potato'); // {p:1, o:2, t:2, a:1}
192 | var letterTally = function(str, obj) {
193 | };
194 |
195 | // 32. Eliminate consecutive duplicates in a list. If the list contains repeated
196 | // elements they should be replaced with a single copy of the element. The order of the
197 | // elements should not be changed.
198 | // compress([1,2,2,3,4,4,5,5,5]) // [1,2,3,4,5]
199 | // compress([1,2,2,3,4,4,2,5,5,5,4,4]) // [1,2,3,4,2,5,4]
200 | var compress = function(list) {
201 | };
202 |
203 | // 33. Augument every element in a list with a new value where each element is an array
204 | // itself.
205 | // augmentElements([[],[3],[7]], 5); // [[5],[3,5],[7,5]]
206 | var augmentElements = function(array, aug) {
207 | };
208 |
209 | // 34. Reduce a series of zeroes to a single 0.
210 | // minimizeZeroes([2,0,0,0,1,4]) // [2,0,1,4]
211 | // minimizeZeroes([2,0,0,0,1,0,0,4]) // [2,0,1,0,4]
212 | var minimizeZeroes = function(array) {
213 | };
214 |
215 | // 35. Alternate the numbers in an array between positive and negative regardless of
216 | // their original sign. The first number in the index always needs to be positive.
217 | // alternateSign([2,7,8,3,1,4]) // [2,-7,8,-3,1,-4]
218 | // alternateSign([-2,-7,8,3,-1,4]) // [2,-7,8,-3,1,-4]
219 | var alternateSign = function(array) {
220 | };
221 |
222 | // 36. Given a string, return a string with digits converted to their word equivalent.
223 | // Assume all numbers are single digits (less than 10).
224 | // numToText("I have 5 dogs and 6 ponies"); // "I have five dogs and six ponies"
225 | var numToText = function(str) {
226 | };
227 |
228 |
229 | // *** EXTRA CREDIT ***
230 |
231 | // 37. Return the number of times a tag occurs in the DOM.
232 | var tagCount = function(tag, node) {
233 | };
234 |
235 | // 38. Write a function for binary search.
236 | // var array = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
237 | // binarySearch(array, 5) // 5
238 | // https://www.khanacademy.org/computing/computer-science/algorithms/binary-search/a/binary-search
239 | var binarySearch = function(array, target, min, max) {
240 | };
241 |
242 | // 39. Write a merge sort function.
243 | // mergeSort([34,7,23,32,5,62]) // [5,7,23,32,34,62]
244 | // https://www.khanacademy.org/computing/computer-science/algorithms/merge-sort/a/divide-and-conquer-algorithms
245 | var mergeSort = function(array) {
246 | };
247 |
248 | // 40. Deeply clone objects and arrays.
249 | // var obj1 = {a:1,b:{bb:{bbb:2}},c:3};
250 | // var obj2 = clone(obj1);
251 | // console.log(obj2); // {a:1,b:{bb:{bbb:2}},c:3}
252 | // obj1 === obj2 // false
253 | var clone = function(input) {
254 | };
255 |
--------------------------------------------------------------------------------
/spec/part2.js:
--------------------------------------------------------------------------------
1 | /* jshint esversion: 6 */
2 |
3 | (function() {
4 | 'use strict';
5 |
6 | describe('More Exercises in Recursion', function() {
7 |
8 | describe('37. Count Tags', function() {
9 | var originalTagCount, actualResults, expectedResults, tags, $child, $rootElement;
10 |
11 | before(function() {
12 | originalTagCount = tagCount;
13 | tagCount = sinon.spy(tagCount);
14 | actualResults = [];
15 | expectedResults = [];
16 | $rootElement = $('