From ac594875c695f3e564ea6ff9d72a985c62d86b4d Mon Sep 17 00:00:00 2001 From: Connor Date: Mon, 16 Jul 2018 09:26:21 -0500 Subject: [PATCH] Completed Recursion --- SpecRunner.html | 2 +- spec/part1.js | 24 ++-- src/recursion.js | 355 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 366 insertions(+), 15 deletions(-) diff --git a/SpecRunner.html b/SpecRunner.html index 5a18ca964..81b5cea16 100644 --- a/SpecRunner.html +++ b/SpecRunner.html @@ -29,7 +29,7 @@ }); - + diff --git a/spec/part1.js b/spec/part1.js index f2ec9ba33..72360c485 100755 --- a/spec/part1.js +++ b/spec/part1.js @@ -84,7 +84,7 @@ - xdescribe('3. Sum Integers in Array', function() { + describe('3. Sum Integers in Array', function() { it('should return a number', function() { expect(typeof(arraySum([[1],[2,3],[[4]],5,6]))).to.eql('number'); @@ -402,7 +402,7 @@ - xdescribe('11. Modulo', function() { + describe('11. Modulo', function() { it('should return a number', function() { expect(typeof(modulo(5,2))).to.equal('number'); @@ -476,7 +476,7 @@ - xdescribe('13. Divide', function() { + describe('13. Divide', function() { it('should return a number', function() { expect(typeof(divide(5,2))).to.equal('number'); @@ -512,7 +512,7 @@ - xdescribe('14. Greatest Common Divisor', function() { + describe('14. Greatest Common Divisor', function() { it('should return a number', function() { expect(typeof(gcd(4,36))).to.equal('number'); @@ -726,7 +726,7 @@ - xdescribe('21. Count key in object', function() { + describe('21. Count key in object', function() { var input = {'e': {'x':'y'}, 't':{'r': {'e':'r'}, 'p': {'y':'r'}},'y':'e'}; it('should return a number', function() { @@ -756,7 +756,7 @@ - xdescribe('22. Count value in object', function() { + describe('22. Count value in object', function() { var input = {'e': {'x':'y'}, 't':{'r': {'e':'r'}, 'p': {'y':'r'}},'y':'e'}; it('should return a number', function() { @@ -786,7 +786,7 @@ - xdescribe('23. Replace keys in object', function() { + describe('23. Replace keys in object', function() { var tallyKeys = function(obj) { var count = 0; @@ -850,7 +850,7 @@ }); - xdescribe('24. First n Fibonacci', function() { + describe('24. First n Fibonacci', function() { it('should return an array', function() { expect(Array.isArray(fibonacci(5))).to.equal(true); @@ -961,7 +961,7 @@ - xdescribe('28. Sum even numbers in nested objects', function() { + describe('28. Sum even numbers in nested objects', function() { var obj = { a: 2, b: {b: 2, bb: {b: 3, bb: {b: 2}}}, @@ -990,7 +990,7 @@ - xdescribe('29. Flatten nested arrays', function() { + describe('29. Flatten nested arrays', function() { it('should return an array', function() { expect(Array.isArray(flatten([1,[2],[3,[[4]]],5]))).to.equal(true); @@ -1073,7 +1073,7 @@ - xdescribe('32. Augment each element in nested arrays', function() { + describe('32. Augment each element in nested arrays', function() { it('should return an array', function() { expect(Array.isArray(augmentElements([[],[3],[7]], 5))).to.equal(true); @@ -1147,7 +1147,7 @@ - xdescribe('35. Convert numbers to text', function() { + describe('35. Convert numbers to text', function() { it('should return a string', function() { expect(typeof(numToText("I have 5 dogs and 6 ponies"))).to.equal('string'); diff --git a/src/recursion.js b/src/recursion.js index e92a8866c..b9f38f1c2 100644 --- a/src/recursion.js +++ b/src/recursion.js @@ -5,31 +5,99 @@ // Example: 5! = 5 x 4 x 3 x 2 x 1 = 120 // factorial(5); // 120 var factorial = function(n) { + if(n < 0){ + return null; + }if(n === 0){ + return 1; + } + return n * factorial(n-1) }; // 2. Compute the sum of an array of integers. // Example: sum([1, 2, 3, 4, 5, 6]); // 21 var sum = function(array) { + + if(array.length === 0){ + return 0; + } + + return array[0] + sum(array.slice(1)) }; // 3. Sum all numbers in an array containing nested arrays. // Example: arraySum([1,[2,3],[[4]],5]); // 15 var arraySum = function(array) { + let sum =0; +if(array.length === 0){ + return sum; +} +for(var i = 0; i 0 ){ + return (n-1) + sumBelow(n-1) + } + }; // 6. Get the integers in range (x, y). // Example: range(2, 9); // [3, 4, 5, 6, 7, 8] var range = function(x, y) { + let retval = []; + if(x === y-1){ + return retval; + } if( x === y +1 ){ + return retval; + } + if(x === y ){ + return retval; + } + if(x < y){ + + retval.push(x+1); + return retval.concat(range(x+1,y)) + } + if( x > y){ + retval.push(x -1); + return retval.concat(range(x-1,y)) + } + }; // 7. Compute the exponent of a number. @@ -38,6 +106,15 @@ var range = function(x, y) { // Example: exponent(4,3); // 64 // https://www.khanacademy.org/computing/computer-science/algorithms/recursive-algorithms/a/computing-powers-of-a-number var exponent = function(base, exp) { + if(exp===0){ + return 1; + } //base case + if(exp < 0) { + return exponent(base,exp+1)/base; + } + return base * exponent(base, exp-1); + + }; // 8. Determine if a number is a power of two. @@ -45,15 +122,30 @@ var exponent = function(base, exp) { // powerOfTwo(16); // true // powerOfTwo(10); // false var powerOfTwo = function(n) { + return n == 1 ? true : (n < 1 ? false : powerOfTwo(n/2)); }; // 9. Write a function that accepts a string a reverses it. var reverse = function(string) { + if(string.length ===0){ + return string; + } + return reverse(string.substring(1)) + string[0] }; // 10. Write a function that determines if a string is a palindrome. var palindrome = function(string) { -}; + string = string.toLowerCase().trim(); + if(string.length< 2){ + return true; + } + if(string[0] === string[string.length-1]){ + // debugger; + return palindrome(string.substring(1,string.length-1)); + } else{ + return false; + } + }; // 11. Write a function that returns the remainder of x divided by y without using the // modulo (%) operator. @@ -61,16 +153,54 @@ var palindrome = function(string) { // modulo(17,5) // 2 // modulo(22,6) // 4 var modulo = function(x, y) { + if (y === 0) { + return NaN; + } + if (x < 0) { return -modulo(-x, y); } + + if (y < 0) { return modulo( x, -y); } + + if (x < y) { return x; } + + return modulo(x - y, y); }; // 12. Write a function that multiplies two numbers without using the * operator or // JavaScript's Math object. var multiply = function(x, y) { + if(y===0){ + return 0; + } + if(y>0){ + return x + multiply(x,y-1); + } + if(y<0){ + return multiply(-x,-y); + } }; // 13. Write a function that divides two numbers without using the / operator or // JavaScript's Math object. var divide = function(x, y) { + if (x === 0 && y === 0) { + return NaN; + } + if (x===0) { + return 0; + } + if (y===1) { + return x; + } + if (x < y) { + return 0; + } + if (x+y < 0) { + return 0; + } + if (x-y < y) { + return 1; + } + return 1 + divide(x-y, y); }; // 14. Find the greatest common divisor (gcd) of two positive numbers. The GCD of two @@ -79,6 +209,16 @@ var divide = function(x, y) { // http://www.cse.wustl.edu/~kjg/cse131/Notes/Recursion/recursion.html // https://www.khanacademy.org/computing/computer-science/cryptography/modarithmetic/a/the-euclidean-algorithm var gcd = function(x, y) { + if(x<0||y<0){ + return null + } + if ( ! y) { + return x; + } + if(x=== -x|| y === -y){ + return null; + } + return gcd(y, x % y); }; // 15. Write a function that compares each character of two strings and returns true if @@ -87,32 +227,80 @@ var gcd = function(x, y) { // compareStr('', '') // true // compareStr('tomato', 'tomato') // true var compareStr = function(str1, str2) { + if(str1[0] !== str2[0]){ + return false; + } + if( str1.length === 0 && str2.length ===0){ + return true; + } + + + return compareStr(str1.substring(1),str2.substring(1)) + }; // 16. Write a function that accepts a string and creates an array where each letter // occupies an index of the array. var createArray = function(str){ + let retval = []; + if(str.length === 0 ){ + return retval; + } + if(str[0]){ + retval.push(str[0]) + } + return retval.concat(createArray(str.substring(1))) }; // 17. Reverse the order of an array var reverseArr = function (array) { + let retval =[]; + if(array.length === 0){ + return retval; + } + if(array[array.length-1]){ + retval.push(array[array.length-1]) + } + return retval.concat(reverseArr(array.slice(0,-1))) }; // 18. Create a new array with a given value and length. // buildList(0,5) // [0,0,0,0,0] // buildList(7,3) // [7,7,7] var buildList = function(value, length) { + let retval = []; + if(length === 0){ + return retval; + } + retval.push(value) + return retval.concat(buildList(value,length-1)) }; // 19. Count the occurence of a value inside a list. // countOccurrence([2,7,4,4,1,4], 4) // 3 // countOccurrence([2,'banana',4,4,1,'banana'], 'banana') // 2 var countOccurrence = function(array, value) { + let count = 0; + if(array.length ===0 ){ + return count; + } + if(array[0]=== value){ + count++ + } + return count + countOccurrence(array.slice(1),value) }; // 20. Write a recursive version of map. // rMap([1,2,3], timesTwo); // [2,4,6] var rMap = function(array, callback) { + let retval = []; + if(array.length === 0){ + return retval; + } + if(array[0]){ + retval.push(callback(array[0])) + } + return retval.concat(rMap(array.slice(1),callback)) }; // 21. Write a function that counts the number of times a key occurs in an object. @@ -120,6 +308,23 @@ var rMap = function(array, callback) { // countKeysInObj(testobj, 'r') // 1 // countKeysInObj(testobj, 'e') // 2 var countKeysInObj = function(obj, key) { + let count = 0; + for(var keys in obj){ + if(keys === key){ + count += 1; + } + if(typeof obj[keys] === "object"){ + count += countKeysInObj(obj[keys],key) + + } + + + + + + } + return count; + }; // 22. Write a function that counts the number of times a value occurs in an object. @@ -127,11 +332,31 @@ var countKeysInObj = function(obj, key) { // countValuesInObj(testobj, 'r') // 2 // countValuesInObj(testobj, 'e') // 1 var countValuesInObj = function(obj, value) { + let count = 0; + for(var keys in obj){ + if(obj[keys] === value){ + count += 1; + } + if(typeof obj[keys] === "object"){ + count += countValuesInObj(obj[keys],value) + } + } + return count; + }; // 23. Find all keys in an object (and nested objects) by a provided name and rename // them to a provided new name while preserving the value stored at that key. var replaceKeysInObj = function(obj, key, newKey) { + for(var keys in obj){ + if(keys === key){ + obj[newKey] = obj[key]; + delete obj[keys] + } if( typeof obj[keys]=== "object"){ + replaceKeysInObj(obj[keys],key,newKey) + } + } + return obj; }; // 24. Get the first n Fibonacci numbers. In the Fibonacci Sequence, each subsequent @@ -140,6 +365,22 @@ var replaceKeysInObj = function(obj, key, newKey) { // fibonacci(5); // [0, 1, 1, 2, 3, 5] // Note: The 0 is not counted. var fibonacci = function(n) { + + if( n < 1){ + return null; + } + if( n === 1){ + return [0,1]; + + }else{ + var fib = fibonacci(n-1) + + fib.push(fib[fib.length-1]+fib[fib.length-2]) + return fib; + } + + + }; // 25. Return the Fibonacci number located at index n of the Fibonacci sequence. @@ -148,17 +389,43 @@ var fibonacci = function(n) { // nthFibo(7); // 13 // nthFibo(3); // 2 var nthFibo = function(n) { + if (n < 0){ + return null; + + }else if(n === 0){ + return 0; + }else if(n === 1 || n === 2){ + return 1; + }else{ + return nthFibo(n - 1) + nthFibo(n - 2); + } }; // 26. Given an array of words, return a new array containing each word capitalized. // var words = ['i', 'am', 'learning', 'recursion']; // capitalizedWords(words); // ['I', 'AM', 'LEARNING', 'RECURSION'] var capitalizeWords = function(input) { + let retval = []; + if (input.length ===0){ + return retval; + } + if(input[0]){ + retval.push(input[0].toUpperCase()) + } + return retval.concat(capitalizeWords(input.slice(1))) }; // 27. Given an array of strings, capitalize the first letter of each index. // capitalizeFirst(['car', 'poop', 'banana']); // ['Car', 'Poop', 'Banana'] var capitalizeFirst = function(array) { + let retval = []; + if(array.length === 0){ + return retval; + } + if(array[0]){ + retval.push(array[0][0].toUpperCase() + array[0].slice(1)) + } + return retval.concat(capitalizeFirst(array.slice(1))) }; // 28. Return the sum of all even numbers in an object containing nested objects. @@ -171,16 +438,49 @@ var capitalizeFirst = function(array) { // }; // nestedEvenSum(obj1); // 10 var nestedEvenSum = function(obj) { + let count = 0; + for(var key in obj){ + if( obj[key]%2 === 0){ + count += obj[key] + }else if(typeof obj[key] === "object"){ + count += nestedEvenSum(obj[key]) + } + } + return count; }; // 29. Flatten an array containing nested arrays. // Example: flatten([1,[2],[3,[[4]]],5]); // [1,2,3,4,5] var flatten = function(arrays) { + let retval = []; + + console.log(retval,arrays) + if(!Array.isArray(arrays)){ + return arrays + } + if(Array.isArray(arrays)){ + for(var i = 0; i < arrays.length; i++){ + retval = retval.concat(flatten(arrays[i])) + } + return retval; + } }; // 30. Given a string, return an object containing tallies of each letter. // letterTally('potato'); // {'p':1, 'o':2, 't':2, 'a':1} -var letterTally = function(str, obj) { +var letterTally = function(str, obj ={}) { + + if(str.length === 0){ + console.log(obj) + return obj + } + if(!obj[str[0]]){ + obj[str[0]] = 1 + }else{ + obj[str[0]]++ + } + return letterTally(str.substring(1),obj) + }; // 31. Eliminate consecutive duplicates in a list. If the list contains repeated @@ -189,18 +489,43 @@ var letterTally = function(str, obj) { // Example: compress([1, 2, 2, 3, 4, 4, 5, 5, 5]) // [1, 2, 3, 4, 5] // Example: compress([1, 2, 2, 3, 4, 4, 2, 5, 5, 5, 4, 4]) // [1, 2, 3, 4, 2, 5, 4] var compress = function(list) { + let retval = []; + if (list.length === 0 ){ + return retval; + } + if(list[0] && list[0]!== list[1]){ + retval.push(list[0]) + } + return retval.concat(compress(list.slice(1))) }; // 32. Augument every element in a list with a new value where each element is an array // itself. // Example: augmentElements([[],[3],[7]], 5); // [[5],[3,5],[7,5]] var augmentElements = function(array, aug) { + let retval = []; +if (array.length === 0){ + return retval; +} + array[0].push(aug) + retval.push(array[0]) +return retval.concat(augmentElements(array.slice(1),aug)) }; // 33. Reduce a series of zeroes to a single 0. // minimizeZeroes([2,0,0,0,1,4]) // [2,0,1,4] // minimizeZeroes([2,0,0,0,1,0,0,4]) // [2,0,1,0,4] var minimizeZeroes = function(array) { + retval = []; + if(array.length === 0){ + return retval; + } + + if(array[0]||array[0] === 0&& array[1]!==0){ + + retval.push(array[0]) + } + return retval.concat(minimizeZeroes(array.slice(1))) }; // 34. Alternate the numbers in an array between positive and negative regardless of @@ -208,12 +533,38 @@ var minimizeZeroes = function(array) { // alternateSign([2,7,8,3,1,4]) // [2,-7,8,-3,1,-4] // alternateSign([-2,-7,8,3,-1,4]) // [2,-7,8,-3,1,-4] var alternateSign = function(array) { + let retval =[]; + if(array.length === 0){ + return retval; + } + if(array.length % 2 ==0){ + retval.push(Math.abs(array[0])) + }else{ + retval.push(-Math.abs(array[0])) + } + return retval.concat(alternateSign(array.slice(1))) }; // 35. Given a string, return a string with digits converted to their word equivalent. // Assume all numbers are single digits (less than 10). // numToText("I have 5 dogs and 6 ponies"); // "I have five dogs and six ponies" var numToText = function(str) { + let newString; + let numToString = ['zero','one','two','three','four','five','six','seven','eight','nine']; + + if(str.length === 0){ + // console.log(str,'here'); + return str + } + //test and see if the any part of the string can be turned into a number + if(Number(str[0])){ + + + + return numToString[Number(str[0])] + numToText(str.slice(1,str.length)) + } else{ + return str[0] + numToText(str.slice(1,str.length)) + } }; // *** EXTRA CREDIT ***