UNPKG

ds-algo-study

Version:

Just experimenting with publishing a package

815 lines (684 loc) 25 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <link href='http://fonts.googleapis.com/css?family=Droid+Sans:700' rel='stylesheet'> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous"> <link rel="stylesheet" href="./prism.css"> <script async defer src="./prism.js"></script> <link rel="stylesheet" href="./style.css"> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous"> <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet"> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> <script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script> <link rel="stylesheet" href="./prism.css"> <script async defer src="./prism.js"></script> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> </head> <pre data-filter-output="(out)" data-role="codeBlock" data-info="js" class="language-javascript data-line line-numbers data-user data-host data-prompt data-output" data-prismjs-copy="Copy !" data-download-link /> <code class="language-javascript"> /* jshint esversion: 6 */ // 1. Calculate the factorial of a number. The factorial of a non-negative integer n, // denoted by n!, is the product of all positive integers less than or equal to n. // Example: 5! = 5 x 4 x 3 x 2 x 1 = 120 // factorial(5); // 120 let factorial = function ( n ) { // base cases if ( n < 0 || n === undefined ) { return null; } if ( n <= 1 ) { return 1; } // recursive case return n * factorial( n - 1 ); }; //--------------------------------------------- // 2. Compute the sum of an array of integers. // sum([1,2,3,4,5,6]); // 21 let sum = function ( array ) { // base case if ( !array.length ) { return 0; } // recursive case return array[ 0 ] + sum( array.slice( 1 ) ); }; //--------------------------------------------- // 3. Sum all numbers in an array containing nested arrays. // arraySum([1,[2,3],[[4]],5]); // 15 let arraySum = function ( array ) { return array.reduce( ( sum, el ) => { // base case: add integer element to sum // recursive case: call arraySum on non-integer element return sum + ( Array.isArray( el ) ? arraySum( el ) : el ) }, 0 ); }; //--------------------------------------------- // 4. Check if a number is even. let isEven = function ( n ) { // base cases if ( n === 0 ) { return true; } if ( n === 1 || n === -1 ) { return false; } // recursive case return isEven( n > 0 ? n - 2 : n + 2 ); }; //--------------------------------------------- // 5. Sum all integers below a given integer. // sumBelow(10); // 45 // sumBelow(7); // 21 let sumBelow = function ( n ) { // base case if ( n === 0 ) { return 0; } // recursive case n = n > 0 ? n - 1 : n + 1; return n + sumBelow( n ); }; //--------------------------------------------- // 6. Get the integers within a range (x, y). // range(2,9); // [3,4,5,6,7,8] let range = function ( x, y ) { // base case if ( y - x === 1 || y - x === 0 ) { return []; } // recursive case y = y > x ? y - 1 : y + 1 return y === x ? [] : range( x, y ).concat( y ); }; //--------------------------------------------- // 7. Compute the exponent of a number. // The exponent of a number says how many times the base number is used as a factor. // 8^2 = 8 x 8 = 64. Here, 8 is the base and 2 is the exponent. // exponent(4,3); // 64 // https://www.khanacademy.org/computing/computer-science/algorithms/recursive-algorithms/a/computing-powers-of-a-number let exponent = function ( base, exp ) { // base case if ( exp === 0 ) { return 1; } // recursive cases! return exp > 0 ? base * exponent( base, exp - 1 ) : 1 / ( base * exponent( base, -1 * exp - 1 ) ); }; //--------------------------------------------- // 8. Determine if a number is a power of two. // powerOfTwo(1); // true // powerOfTwo(16); // true // powerOfTwo(10); // false let powerOfTwo = function ( n ) { // base cases if ( n === 1 ) { return true; } if ( n === 0 || n % 2 === 1 ) { return false; } // recursive case return powerOfTwo( n / 2 ); }; //--------------------------------------------- // 9. Write a function that reverses a string. let reverse = function ( string ) { // base case: resolve to empty string // recursive case: call reverse on substring return string === '' ? '' : reverse( string.substr( 1 ) ) + string.charAt( 0 ); }; //--------------------------------------------- // 10. Write a function that determines if a string is a palindrome. let palindrome = function ( string ) { // base cases if ( string === '' || string.length === 1 ) { return true; } if ( string[ 0 ].toLowerCase() !== string.slice( -1 ).toLowerCase() ) { return false; } // recursive case return palindrome( string.substr( 1, string.length - 2 ) ); }; //--------------------------------------------- // 11. Write a function that returns the remainder of x divided by y without using the // modulo (%) operator. // modulo(5,2) // 1 // modulo(17,5) // 2 // modulo(22,6) // 4 let modulo = function ( x, y ) { if ( y === 0 ) { return NaN; } if ( x < 0 && y < 0 ) { if ( x > y ) { return x; } } else if ( ( x < 0 && y > 0 ) || ( x > 0 && y < 0 ) ) { if ( -x < y ) { return x; } return modulo( x + y, y ); } else { if ( x < y ) { return x; } } return modulo( x - y, y ); }; //--------------------------------------------- // 12. Write a function that multiplies two numbers without using the * operator or // Math methods. let multiply = function ( x, y ) { if ( x === 0 || y === 0 ) { return 0; } else if ( y < 0 ) { return -x + multiply( x, y + 1 ); } else { return x + multiply( x, y - 1 ); } }; //--------------------------------------------- // 13. Write a function that divides two numbers without using the / operator or // Math methods to arrive at an approximate quotient (ignore decimal endings). let divide = function ( x, y ) { if ( y === 0 ) { return NaN; } if ( x === 0 ) { return 0; } if ( x < 0 && y > 0 && -x < y || x < -y ) { return 0; } if ( x > 0 && y > 0 && x < y ) { return 0; } if ( x > 0 && y > 0 ) { return 1 + divide( x - y, y ); } else { return -1 + divide( x + y, y ); } } //--------------------------------------------- // 14. Find the greatest common divisor (gcd) of two positive numbers. The GCD of two // integers is the greatest integer that divides both x and y with no remainder. // gcd(4,36); // 4 // http://www.cse.wustl.edu/~kjg/cse131/Notes/Recursion/recursion.html // https://www.khanacademy.org/computing/computer-science/cryptography/modarithmetic/a/the-euclidean-algorithm let gcd = function ( x, y ) { // base cases if ( x < 0 || y < 0 ) { return null; } if ( y % x === 0 ) { return x; } // recursive cases return x > y ? gcd( y, x ) : gcd( x, y % x ); }; //--------------------------------------------- // 15. Write a function that compares each character of two strings and returns true if // both are identical. // compareStr('house', 'houses') // false // compareStr('tomato', 'tomato') // true let compareStr = function ( str1, str2 ) { // base cases if ( str1 === '' && str2 === '' ) { return true; } if ( str1.charAt( 0 ) !== str2.charAt( 0 ) ) { return false; } // recursive case return compareStr( str1.substr( 1 ), str2.substr( 1 ) ); }; //--------------------------------------------- // 16. Write a function that accepts a string and creates an array where each letter // occupies an index of the array. let createArray = function ( str ) { // base case: resolve to array containing first character of string // recursive case: concatenate results of calling createArray on substrings return str.length === 1 ? [ str.charAt( 0 ) ] : [ str.charAt( 0 ) ].concat( createArray( str.substr( 1 ) ) ); }; //--------------------------------------------- // 17. Reverse the order of an array let reverseArr = function ( array ) { // base case: resolve to (original) empty array // recursive case: call reverseArray on sliced array and concatenate with first element return !array.length ? array : reverseArr( array.slice( 1 ) ).concat( array[ 0 ] ); }; //--------------------------------------------- // 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] let buildList = function ( value, length ) { // base case: resolve to empty array // recursive case: concatenate results of calling buildList on value and decremented length return length === 0 ? [] : [ value ].concat( buildList( value, length - 1 ) ); }; //--------------------------------------------- // 19. Implement FizzBuzz. Given integer n, return an array of the string representations of 1 to n. // For multiples of three, output 'Fizz' instead of the number. // For multiples of five, output 'Buzz' instead of the number. // For numbers which are multiples of both three and five, output "FizzBuzz" instead of the number. // fizzBuzz(5) // ['1','2','Fizz','4','Buzz'] let fizzBuzz = function ( n ) { let results = []; let val = n; // base case if ( n === 0 ) { return results; } // recursive cases if ( n % 3 === 0 && n % 5 !== 0 ) { val = 'Fizz'; } if ( n % 3 !== 0 && n % 5 === 0 ) { val = 'Buzz'; } if ( n % 3 === 0 && n % 5 === 0 ) { val = 'FizzBuzz'; } results.push( val.toString() ); return fizzBuzz( n - 1 ).concat( results ); }; //--------------------------------------------- // 20. Count the occurence of a value in a list. // countOccurrence([2,7,4,4,1,4], 4) // 3 // countOccurrence([2,'banana',4,4,1,'banana'], 'banana') // 2 let countOccurrence = function ( array, value ) { // base case if ( array.length === 0 ) { return 0; } // recursive case let increment; if (array[ 0 ] === value) { increment = 1; } else { increment = 0; } return increment + countOccurrence( array.slice( 1 ), value ); }; // 21. Write a recursive version of map. // rMap([1,2,3], timesTwo); // [2,4,6] //--------------------------------Without Recursion------ // Write a function using fat arrow syntax named`arrowMyMap` that accepts an array // and a callback as arguments.The function will return an array of new elements // obtained by calling the callback on each element of the array, passing in the // element.Assign the below function to a letiable using the const keyword. // // Do not use the built in Array#map - use Array#forEach for iteration. // // // Examples: // let result1 = arrowMyMap( [ 100, 25, 81, 64 ], Math.sqrt ); // console.log( result1 ); // [ 10, 5, 9, 8 ] // // const yell = el => el.toUpperCase() + '!' // // let result2 = arrowMyMap( [ 'run', 'Forrest' ], yell ); // console.log( result2 ); // [ 'RUN!', 'FORREST!' ] // // *********************************************************************** / // // const arrowMyMap = ( array, cb ) => { // let mapped = []; // // array.forEach( el => mapped.push( cb( el ) ) ); // return mapped; // }; //--------------------------------With Recursion------ let rMap = function ( array, callback ) { if ( array.length === 0 ) return []; let list = rMap( array.slice( 1, array.length ), callback ); list.unshift( callback( array[ 0 ] ) ); return list; }; // 22. Write a function that counts the number of times a key occurs in an object. // let obj = {'e':{'x':'y'},'t':{'r':{'e':'r'},'p':{'y':'r'}},'y':'e'}; // countKeysInObj(obj, 'r') // 1 // countKeysInObj(obj, 'e') // 2 let countKeysInObj = function ( obj, key ) { let count = 0; for ( let prop in obj ) { if ( prop === key ) { count++; } if ( obj[ prop ] instanceof Object ) { count += countKeysInObj( obj[ prop ], key ); } } return count; }; // 23. Write a function that counts the number of times a value occurs in an object. // let obj = {'e':{'x':'y'},'t':{'r':{'e':'r'},'p':{'y':'r'}},'y':'e'}; // countValuesInObj(obj, 'r') // 2 // countValuesInObj(obj, 'e') // 1 let countValuesInObj = function ( obj, value ) { let count = 0; for ( let prop in obj ) { if ( obj[ prop ] === value ) count++; if ( obj[ prop ] instanceof Object ) { count += countValuesInObj( obj[ prop ], value ); } } return count; }; // 24. 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. let replaceKeysInObj = function ( obj, oldKey, newKey ) { for ( let prop in obj ) { if ( prop === oldKey ) { obj[ newKey ] = obj[ prop ]; delete obj[ prop ]; } if ( obj[ prop ] instanceof Object ) { replaceKeysInObj( obj[ prop ], oldKey, newKey ); } } return obj; }; // 25. Get the first n Fibonacci numbers. In the Fibonacci sequence, each subsequent // number is the sum of the previous two. // Example: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34..... // fibonacci(5); // [0,1,1,2,3,5] // Note: The 0 is not counted. let fibonacci = function ( n ) { if ( n <= 0 ) return null; if ( n === 1 ) return [ 0, 1 ]; let list = fibonacci( n - 1 ); if ( list[ n ] !== undefined ) return list[ n ]; list[ n ] = list[ n - 1 ] + list[ n - 2 ]; return list; }; // 26. Return the Fibonacci number located at index n of the Fibonacci sequence. // [0,1,1,2,3,5,8,13,21] // nthFibo(5); // 5 // nthFibo(7); // 13 // nthFibo(3); // 2 let nthFibo = function ( n ) { if ( n < 0 ) return null; if ( n === 0 ) return 0; if ( n === 1 ) return 1; return nthFibo( n - 1 ) + nthFibo( n - 2 ); }; // 27. Given an array of words, return a new array containing each word capitalized. // let words = ['i', 'am', 'learning', 'recursion']; // capitalizedWords(words); // ['I', 'AM', 'LEARNING', 'RECURSION'] let capitalizeWords = function ( array ) { if ( array.length === 0 ) return []; let list = capitalizeWords( array.slice( 1, array.length ) ); list.unshift( array[ 0 ].toUpperCase() ); return list; }; // 28. Given an array of strings, capitalize the first letter of each index. // capitalizeFirst(['car','poop','banana']); // ['Car','Poop','Banana'] let capitalizeFirst = function ( array ) { if ( array.length === 0 ) return []; let list = capitalizeFirst( array.slice( 1, array.length ) ); list.unshift( array[ 0 ][ 0 ].toUpperCase() + array[ 0 ].substring( 1 ) ); return list; }; // 29. Return the sum of all even numbers in an object containing nested objects. // let obj1 = { // a: 2, // b: {b: 2, bb: {b: 3, bb: {b: 2}}}, // c: {c: {c: 2}, cc: 'ball', ccc: 5}, // d: 1, // e: {e: {e: 2}, ee: 'car'} // }; // nestedEvenSum(obj1); // 10 let nestedEvenSum = function ( obj ) { let sum = 0; for ( let prop in obj ) { if ( obj[ prop ] % 2 === 0 ) sum += obj[ prop ]; if ( obj[ prop ] instanceof Object ) sum += nestedEvenSum( obj[ prop ] ); } return sum; }; // 30. Flatten an array containing nested arrays. // flatten([1,[2],[3,[[4]]],5]); // [1,2,3,4,5] let flatten = function ( array ) { let list = []; if ( array.length === 0 ) return []; for ( let i = 0; i < array.length; i++ ) { if ( array[ i ] instanceof Array ) { list.push( ...flatten( array[ i ] ) ); } else { list.push( array[ i ] ); } } return list; }; // 31. Given a string, return an object containing tallies of each letter. // letterTally('potato'); // {p:1, o:2, t:2, a:1} let letterTally = function ( str, obj = {} ) { if ( str.length === 0 ) return obj; letterTally( str.substring( 1 ), obj ); if ( obj[ str[ 0 ] ] === undefined ) { obj[ str[ 0 ] ] = 1; } else { obj[ str[ 0 ] ] += 1; } return obj; }; // 32. Eliminate consecutive duplicates in a list. If the list contains repeated // elements they should be replaced with a single copy of the element. The order of the // elements should not be changed. // compress([1,2,2,3,4,4,5,5,5]) // [1,2,3,4,5] // compress([1,2,2,3,4,4,2,5,5,5,4,4]) // [1,2,3,4,2,5,4] let compress = function ( list ) { if ( list.length === 0 ) return []; let res = compress( list.slice( 1 ) ); if ( list[ 0 ] !== res[ 0 ] ) { res.unshift( list[ 0 ] ); } return res; }; // 33. Augument every element in a list with a new value where each element is an array // itself. // augmentElements([[],[3],[7]], 5); // [[5],[3,5],[7,5]] let augmentElements = function ( array, aug ) { if ( array.length === 0 ) return []; let list = augmentElements( array.slice( 1 ), aug ); array[ 0 ].push( aug ); list.unshift( array[ 0 ] ); return list; }; // 34. 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] let minimizeZeroes = function ( array ) { if ( array.length === 0 ) return []; let list = minimizeZeroes( array.slice( 1 ) ); if ( ( array[ 0 ] === 0 ^ list[ 0 ] === 0 ) || array[ 0 ] !== 0 ) { list.unshift( array[ 0 ] ); } return list; }; // 35. Alternate the numbers in an array between positive and negative regardless of // their original sign. The first number in the index always needs to be positive. // 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] let alternateSign = function ( array ) { if ( array.length === 0 ) return []; let list = alternateSign( array.slice( 0, array.length - 1 ) ); let lng = array.length; if ( lng % 2 === 0 ) { if ( array[ lng - 1 ] > 0 ) { array[ lng - 1 ] = -array[ lng - 1 ]; } } else { if ( array[ lng - 1 ] < 0 ) { array[ lng - 1 ] = -array[ lng - 1 ]; } } list.push( array[ lng - 1 ] ); return list; }; // 36. 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" let numToText = function ( str ) { if ( str.length === 0 ) return ''; let tempStr = numToText( str.substring( 0, str.length - 1 ) ); let replace; switch ( str[ str.length - 1 ] ) { case '1': replace = 'one'; break; case '2': replace = 'two'; break; case '3': replace = 'three'; break; case '4': replace = 'four'; break; case '5': replace = 'five'; break; case '6': replace = 'six'; break; case '7': replace = 'seven'; break; case '8': replace = 'eight'; break; case '9': replace = 'nine'; break; default: replace = str[ str.length - 1 ]; break; } return tempStr + replace; }; // *** EXTRA CREDIT *** // 37. Return the number of times a tag occurs in the DOM. let tagCount = function ( tag, node ) { }; // 38. Write a function for binary search. // let array = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]; // binarySearch(array, 5) // 5 // https://www.khanacademy.org/computing/computer-science/algorithms/binary-search/a/binary-search let binarySearch = function ( array, target, min = 0, max = array.length - 1 ) { if ( array.length === 0 ) return null; if ( min > max ) return null; let mid = Math.floor( ( max - min ) / 2 ) + min; if ( array[ mid ] < target ) { return binarySearch( array, target, mid + 1, max ); } else if ( array[ mid ] > target ) { return binarySearch( array, target, min, mid - 1 ); } else { return mid; } }; // 39. Write a merge sort function. // mergeSort([34,7,23,32,5,62]) // [5,7,23,32,34,62] // https://www.khanacademy.org/computing/computer-science/algorithms/merge-sort/a/divide-and-conquer-algorithms let mergeSort = function ( array ) { if ( array.length === 0 || array.length === 1 ) return array; let mid = Math.floor( array.length / 2 ); let left = array.slice( 0, mid ); let right = array.slice( mid, array.length ); return merge( mergeSort( left ), mergeSort( right ) ); }; function merge ( left, right ) { let res = []; let l = 0; let r = 0; while ( l < left.length && r < right.length ) { if ( left[ l ] < right[ r ] ) { res.push( left[ l++ ] ); } else { res.push( right[ r++ ] ); } } return res.concat( left.slice( l ) ).concat( right.slice( r ) );; } // 40. Deeply clone objects and arrays. // let obj1 = {a:1,b:{bb:{bbb:2}},c:3}; // let obj2 = clone(obj1); // console.log(obj2); // {a:1,b:{bb:{bbb:2}},c:3} // obj1 === obj2 // false let clone = function ( input ) { let res; if ( Array.isArray( input ) ) { res = []; if ( input.length === 0 ) return []; for ( let i = 0; i < input.length; i++ ) { if ( input[ i ] instanceof Object ) { res.push( clone( input[ i ] ) ); } else { res.push( input[ i ] ); } } } else { if ( input === null ) return {}; res = {}; for ( let prop in input ) { if ( input[ prop ] instanceof Object ) { res[ prop ] = clone( input[ prop ] ); } else { res[ prop ] = input[ prop ]; } } } return res; }; </code></pre> <body> <script async defer> $( document ).ready( function () { $( 'code, pre' ).append( '<span class="command-copy"><i class="fa fa-clipboard" aria-hidden="true"></i></span>' ); $( 'code span.command-copy' ).click( function ( e ) { var text = $( this ).parent().text().trim(); //.text(); var copyHex = document.createElement( 'input' ); copyHex.value = text document.body.appendChild( copyHex ); copyHex.select(); document.execCommand( 'copy' ); console.log( copyHex.value ) document.body.removeChild( copyHex ); } ); $( 'pre span.command-copy' ).click( function ( e ) { var text = $( this ).parent().text().trim(); var copyHex = document.createElement( 'input' ); copyHex.value = text document.body.appendChild( copyHex ); copyHex.select(); document.execCommand( 'copy' ); console.log( copyHex.value ) document.body.removeChild( copyHex ); } ); } ) </script> <script async defer> document.querySelectorAll( 'pre > code' ).forEach( function ( codeBlock ) { var button = document.createElement( 'button' ); button.className = 'copy-code-button'; button.type = 'button'; button.innerText = 'Copy'; var pre = codeBlock.parentNode; if ( pre.parentNode.classList.contains( 'highlight' ) ) { var highlight = pre.parentNode; highlight.parentNode.insertBefore( button, highlight ); } else { pre.parentNode.insertBefore( button, pre ); } } ); document.querySelector( 'button' ).addEventListener( 'click', () => { const code = document.getElementByTagName( 'code' ); navigator.clipboard.writeText( code.innerHTML ); } ); </script> </body> </html>