├── .gitignore ├── README.md ├── balancedParens └── balancedParens.js ├── binarySearchArray └── binarySearchArray.js ├── bubbleSort └── bubbleSort.js ├── characterFrequency └── characterFrequency.js ├── coinSums └── coinSums.js ├── commonAncestor └── commonAncestor.js ├── commonCharacters └── commonCharacters.js ├── constantTimeStackMin └── constantTimeStackMin.js ├── deepEquality └── deepEquality.js ├── evenOccurrence └── evenOccurrence.js ├── eventingLibrary └── eventingLibrary.js ├── functionBind └── functionBind.js ├── hashTable └── hashTable.js ├── hashTableResizing └── hashTableResizing.js ├── htmljQueryColor ├── README.md ├── index.html ├── lib │ └── jquery.js └── main.js ├── implementingOperators └── implementingOperators.js ├── insertionSort └── insertionSort.js ├── isSubsetOf └── isSubsetOf.js ├── jsonpFetcher ├── jsonpFetcher.html └── jsonpFetcher.js ├── key-concepts.js ├── key-concepts.rb ├── largestProductOfThree └── largestProductOfThree.js ├── linkedList └── linkedList.js ├── linkedListCycles └── linkedListCycles.js ├── longestPalindrome └── longestPalindrome.js ├── longestRun └── longestRun.js ├── nonrepeatedCharacter └── nonrepeatedCharacter.js ├── nthFibonacci └── nthFibonacci.js ├── numberToEnglish └── numberToEnglish.js ├── powerSet └── powerSet.js ├── primeTester └── primeTester.js ├── queueStack └── queueStack.js ├── rangeClass └── rangeClass.js ├── redo.js ├── reverseArray └── reverseArray.js ├── robotPaths └── robotPaths.js ├── rockPaperScissors └── rockPaperScissors.js ├── rockPaperScissorsII └── rockPaperScissors.js ├── romanNumeralTranslator └── romanNumeralTranslator.js ├── rotateMatrix └── rotateMatrix.js ├── shuffleDeck └── shuffleDeck.js ├── sortableTable ├── index.html ├── lib │ └── jquery-2.1.0.min.js └── sortableTable.js ├── spiralTraversal └── spiralTraversal.js ├── sumArray └── sumArray.js ├── telephoneWords └── telephoneWords.js ├── tree └── tree.js ├── treeBFSelect └── treeBFSelect.js ├── treeCountLeaves └── treeCountLeaves.js ├── treeDFselect └── treeDFSelect.js └── treeMap └── treeMap.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .gitignore 3 | balancedParens.js 4 | binarySearchArray.js 5 | coinSums.js 6 | combinations.js 7 | commonCharacters.js 8 | flipParens.js 9 | isSubsetOf.js 10 | permutations.js 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Toy Problems ## 2 | 3 | This repo contains a list of toy problems which are meant to be solved using JavaScript. Toy problems are small coding challenges meant for mental exercise and can be used to refresh some computer science and JavaScript concepts. -------------------------------------------------------------------------------- /balancedParens/balancedParens.js: -------------------------------------------------------------------------------- 1 | /* 2 | * write a function that takes a string of text and returns true if 3 | * the parentheses are balanced and false otherwise. 4 | * 5 | * Example: 6 | * balancedParens('('); // false 7 | * balancedParens('()'); // true 8 | * balancedParens(')('); // false 9 | * balancedParens('(())'); // true 10 | * 11 | * Step 2: 12 | * make your solution work for all types of brackets 13 | * 14 | * Example: 15 | * balancedParens('[](){}'); // true 16 | * balancedParens('[({})]'); // true 17 | * balancedParens('[(]{)}'); // false 18 | * 19 | * Step 3: 20 | * ignore non-bracket characters 21 | * balancedParens(' var wow = { yo: thisIsAwesome() }'); // true 22 | * balancedParens(' var hubble = function() { telescopes.awesome();'); // false 23 | * 24 | * 25 | */ 26 | 27 | var balancedParens = function (input) { 28 | var stack = []; 29 | var map = { 30 | ')' : '(', 31 | ']' : '[', 32 | '}' : '{' 33 | }; 34 | var length = input.length; 35 | var i, currentChar, popped; 36 | 37 | for (i = 0; i < length; i += 1) { 38 | currentChar = input[i]; 39 | 40 | if ( isOpening(currentChar) ) { 41 | stack.push( currentChar ); 42 | } else if ( isClosing(currentChar) ) { 43 | popped = stack.pop(); 44 | if ( map[currentChar] !== popped ) { 45 | return false; 46 | } 47 | } 48 | } 49 | 50 | return stack.length === 0; 51 | }; 52 | 53 | var isOpening = function (char) { 54 | return char === '(' || char === '[' || char === '{'; 55 | }; 56 | 57 | var isClosing = function (char) { 58 | return char === ')' || char === ']' || char === '}'; 59 | }; -------------------------------------------------------------------------------- /binarySearchArray/binarySearchArray.js: -------------------------------------------------------------------------------- 1 | /* 2 | given a sorted array, find the index of an element 3 | using a binary search algorithm. 4 | 5 | Test for linear vs binary by applying a data set that 6 | exhibits the desired characteristics. 7 | */ 8 | 9 | /** 10 | * example usage 11 | * var index = binarySearch([1, 2, 3, 4, 5], 3); 12 | * console.log(index); // [2] 13 | **/ 14 | 15 | var binarySearch = function (array, element) { 16 | var length, mid, midValue, left, right, result; 17 | 18 | // check for allowable conditions 19 | if ( Array.isArray(array) && typeof element === 'number' ) { 20 | length = array.length; 21 | mid = Math.floor( length / 2 ); 22 | midValue = array[mid]; 23 | left = array.slice(0, mid); 24 | right = array.slice(mid + 1); 25 | result = 0; 26 | 27 | if (length === 0) { 28 | // base condition 29 | return null; 30 | // result = null; 31 | } else if ( midValue === element ) { 32 | return mid; 33 | // result = mid; 34 | } else if ( midValue > element ) { 35 | return binarySearch( left, element ); 36 | // result = binarySearch( left, element ); 37 | } else { 38 | var temp = binarySearch( right, element ); 39 | // result = temp === null ? temp : mid + temp + 1; 40 | return temp === null ? temp : mid + temp + 1; 41 | } 42 | // return result; 43 | } 44 | }; 45 | 46 | 47 | // Space Complexity O(log n) b/c of recursive stack 48 | var binarySearch = function (array, element) { 49 | var inner = function (lowerBound, upperBound) { 50 | var mid = Math.floor( (lowerBound + upperBound) / 2 ); 51 | var midValue = array[mid]; 52 | 53 | /* 54 | * base condition: if the mid index is either of the bounds, 55 | * then if neither of the array values at the index doesn't 56 | * equal the value, then the value can't be found in the array 57 | */ 58 | if ( mid === lowerBound || mid === upperBound ) { 59 | return midValue === element ? mid : null; 60 | } else if (midValue === element) { 61 | return mid; 62 | } else if (midValue > element) { 63 | return inner(lowerBound, mid); 64 | } else { 65 | return inner(mid, upperBound); 66 | } 67 | }; 68 | 69 | // check for allowable conditions 70 | if ( !Array.isArray(array) ) { 71 | throw new Error('Need to pass in a valid Array object'); 72 | } else if ( typeof element !== 'number' ) { 73 | throw new Error('Need to pass in a valid Number to find in Array'); 74 | } else { 75 | return inner(0, array.length); 76 | } 77 | }; -------------------------------------------------------------------------------- /bubbleSort/bubbleSort.js: -------------------------------------------------------------------------------- 1 | /*jshint expr:true*/ 2 | 3 | /* 4 | * Bubble sort is the most basic sorting algorithm in all of Computer 5 | * Sciencedom. It works by starting at the first element of an array and 6 | * comparing it to the second element; if the first element is greater than the 7 | * second element, it swaps the two. It then compares the second to the third, 8 | * and the third to the fourth, and so on; in this way, the largest values 9 | * "bubble" to the end of the array. Once it gets to the end of the array, it 10 | * starts over and repeats the process until the array is sorted numerically. 11 | * 12 | * Implement a function that takes an array and sorts it using this technique. 13 | * Don't use JavaScript's built-in sorting function (Array.prototype.sort). 14 | * 15 | * QUERY: What's the time complexity of your algorithm? If you don't already 16 | * know, try to intuit this without consulting the Googles. 17 | * 18 | * Extra credit: Optimization time! During any given pass, if no elements are 19 | * swapped we can assume the list is sorted and can exit the function early. 20 | * After this optimization, what is the time complexity of your algorithm? 21 | * 22 | * Moar credits: Do you need to consider every element every time you iterate 23 | * through the array? Make it happen, boss. Again: Has the time complexity of 24 | * your algorithm changed? 25 | */ 26 | 27 | /* 28 | * Example usage: 29 | * bubbleSort([2, 1, 3]); // yields [1, 2, 3] 30 | * 31 | */ 32 | 33 | // Introduce i into the global scope so we can test function efficiency 34 | var i; 35 | 36 | // Feel free to add helper functions if needed. 37 | 38 | var bubbleSort = function(array) { 39 | var length = array.length; 40 | var i, j, temp, noSwap; 41 | 42 | for (j = 0; j < length; j += 1) { 43 | noSwap = true; 44 | for (i = 0; i < length - j - 1; i += 1) { 45 | if (array[i] > array[i + 1]) { 46 | // swap 47 | temp = array[i]; 48 | array[i] = array[i + 1]; 49 | array[i + 1] = temp; 50 | noSwap = false; 51 | } 52 | } 53 | if (noSwap) { break; } 54 | } 55 | 56 | return array; 57 | }; 58 | -------------------------------------------------------------------------------- /characterFrequency/characterFrequency.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Write a function that takes as its input a string and returns an array of 3 | * arrays as shown below sorted in descending order by frequency and then by 4 | * ascending order by character. 5 | * 6 | * 7 | * :: Example :: 8 | * 9 | * characterFrequency('mississippi') === 10 | * [ 11 | * ['i', 4], 12 | * ['s', 4], 13 | * ['p', 2], 14 | * ['m', 1] 15 | * ] 16 | * 17 | * :: Gotcha :: 18 | * 19 | * characterFrequency('miaaiaaippi') === 20 | * [ 21 | * ['a', 4], 22 | * ['i', 4], 23 | * ['p', 2], 24 | * ['m', 1] 25 | * ] 26 | * 27 | * 28 | */ 29 | 30 | // O(n*log(n)) + O(n) + O(n) => O(n*log(n)) 31 | var characterFrequency = function (string) { 32 | var freq = {}; 33 | var result = []; 34 | var length = string.length; 35 | var i, prop, temp; 36 | 37 | // O(n) 38 | for (i = 0; i < length; i += 1) { 39 | if (freq[string[i]] === void 0) { 40 | freq[string[i]] = 1; 41 | } else { 42 | freq[string[i]] += 1; 43 | } 44 | } 45 | 46 | // freq is an object with all the frequencies for each character 47 | // O(n) 48 | for (prop in freq) { 49 | result.push( [prop, freq[prop]] ); 50 | } 51 | 52 | // result is an array of [character, frequency]'s 53 | // O(n*log(n)) 54 | mergeSort(result); 55 | 56 | return result; 57 | }; 58 | 59 | // O(n*log(n)) 60 | var mergeSort = function (array) { 61 | var length = array.length; 62 | 63 | if (length < 2) { return array; } 64 | 65 | var mid = Math.floor( length / 2 ); 66 | var left = array.slice(0, mid); 67 | var right = array.slice(mid); 68 | 69 | left = mergeSort(left); 70 | right = mergeSort(right); 71 | merge(array, left, right); 72 | 73 | return array; 74 | }; 75 | 76 | var merge = function (array, left, right) { 77 | // each element in any of the arrays is an array of [character, frequency] 78 | var a = 0; 79 | var l = 0; 80 | var r = 0; 81 | var aLen = array.length; 82 | var lLen = left.length; 83 | var rLen = right.length; 84 | 85 | while (l < lLen && r < rLen) { 86 | if (left[l][1] < right[r][1]) { 87 | // descending order 88 | array[a] = right[r]; 89 | a += 1; 90 | r += 1; 91 | } else if (left[l][1] > right[r][1]) { 92 | array[a] = left[l]; 93 | a += 1; 94 | l += 1; 95 | } else { 96 | // when the frequencies are equal 97 | if ( getCharCode(left[l][0]) < getCharCode(right[r][0]) ) { 98 | array[a] = left[l]; 99 | a += 1; 100 | l += 1; 101 | } else { 102 | array[a] = right[r]; 103 | a += 1; 104 | r += 1; 105 | } 106 | } 107 | } 108 | 109 | // by the time the above while loop terminates, either left or right arrays 110 | // is still not exhausted 111 | while (l < lLen) { 112 | array[a] = left[l]; 113 | a += 1; 114 | l += 1; 115 | } 116 | 117 | while (r < rLen) { 118 | array[a] = right[r]; 119 | a += 1; 120 | r += 1; 121 | } 122 | }; 123 | 124 | var getCharCode = function (character) { 125 | return String.prototype.charCodeAt.call(character); 126 | }; -------------------------------------------------------------------------------- /coinSums/coinSums.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | In England the currency is made up of pound, £, and pence, p, and there are eight coins in general circulation: 4 | 5 | 1p piece 6 | 2p piece 7 | 5p piece 8 | 10p piece 9 | 20p piece 10 | 50p piece 11 | 1 euro (100p) 12 | 2 euro (200p) 13 | 14 | It is possible to make £2 in the following way: 15 | 16 | 1 * £1 + 1 * 50p + 2 * 20p + 1 * 5p + 1 * 2p + 3 * 1p 17 | How many different ways can £2 be made using any number of coins? 18 | 19 | example usage of `makeChange`: 20 | 21 | // aka, there's only one way to make 1p. that's with a single 1p piece 22 | makeChange(1) === 1 23 | // aka, there's only two ways to make 2p. that's with two, 1p pieces or with a single 2p piece 24 | makeChange(2) === 2 25 | */ 26 | 27 | var makeChange = function (total) { 28 | if (arguments.length < 1 || typeof total !== 'number') { 29 | throw new Error('Need to provide a numeric value'); 30 | } 31 | 32 | var inner = function (total, coins) { 33 | // base cases 34 | if (total < 0) { 35 | return 0; 36 | } else if (total === 0) { 37 | return 1; 38 | } 39 | 40 | var result = 0; 41 | var i, temp; 42 | 43 | /* 44 | * As an example, if total === 16, then what you want to calculate is the sum of the following: 45 | * 1) The number of ways to use one 10 coin and makeChange(6, with only coins less than or equal to 10) 46 | * 2) The number of ways to use one 5 coin and makeChange(11, with only coins less than or equal to 5) 47 | * 3) The number of ways to use one 2 coin and makeChange(14, with only coins less than or equal to 2) 48 | * 4) The number of ways to use one 1 coin and makeChange(15, with only coins less than or equal to 1) 49 | * The reason you have to stipulate what coins are available to use is because by doing so, you avoid 50 | * double counting the combinations. 51 | */ 52 | 53 | // for each coin available to use 54 | for (i = 0; i < coins.length; i += 1) { 55 | // subtract that amount from total and call makeChange with new total and updated coinsAvailable 56 | result += inner( total - coins[i], coinsAvailable(coins[i]) ); 57 | } 58 | 59 | return result; 60 | }; 61 | 62 | return inner( total, coinsAvailable(total) ); 63 | }; 64 | 65 | var coinsAvailable = function (num) { 66 | var coins = [200, 100, 50, 20, 10, 5, 2, 1]; 67 | return coins.filter(function (n) { 68 | return n <= num; 69 | }); 70 | }; 71 | 72 | // Implementation using Reduce 73 | // var makeChange = function (num) { 74 | // var inner = function (num, coins) { 75 | // if (num < 0) return 0; 76 | // if (num === 0) return 1; 77 | // 78 | // return coins.reduce(function (acc, cur) { 79 | // return acc + inner(num - cur, coinsAvailable(cur)); 80 | // }, 0); 81 | // }; 82 | // 83 | // return inner(num, coinsAvailable(num)); 84 | // }; -------------------------------------------------------------------------------- /commonAncestor/commonAncestor.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * implement the function `getClosestCommonAncestor` and `getAncestorPath` 4 | * in the following Tree class 5 | */ 6 | 7 | /** example usage: 8 | * var grandma = new Tree('grandma'); 9 | * var mom = new Tree('mom'); 10 | * grandma.addChild(mom); 11 | * var me = new Tree('me'); 12 | * mom.addChild(me); 13 | * grandma.getAncestorPath(me); // => [grandma, mom, me] 14 | */ 15 | 16 | var Tree = function (name) { 17 | this.name = name; 18 | this.children = []; 19 | }; 20 | 21 | /** 22 | * add an immediate child 23 | */ 24 | Tree.prototype.addChild = function (child) { 25 | if (!this.isDescendant(child)) { 26 | this.children.push(child); 27 | }else { 28 | throw new Error("That child is already a child of this tree"); 29 | } 30 | return this; 31 | }; 32 | 33 | /** 34 | * return the lowest common ancestor of the two child nodes. 35 | * (assume for these examples that only a women can be the parent of a child) 36 | * more examples: 37 | * 1.) between me and my brother -> my mom 38 | * 2.) between me and my cousin -> my grandma 39 | * 3.) between my grandma and my grandma -> my grandma 40 | * 4.) between me and a potato -> null 41 | */ 42 | Tree.prototype.getClosestCommonAncestor = function (node1, node2) { 43 | if (arguments.length < 2) { 44 | throw new Error('Need two nodes as input'); 45 | } 46 | 47 | // get ancestor path of both nodes 48 | var ancestorPath1 = this.getAncestorPath(node1); 49 | var ancestorPath2 = this.getAncestorPath(node2); 50 | 51 | var result = null; 52 | var ancestor2Object, ancestor1Len, ancestor2Len, i, j; 53 | 54 | if (ancestorPath1 === null || ancestorPath2 === null) { return null; } 55 | 56 | ancestor2Object = {}; 57 | ancestor1Len = ancestorPath1.length; 58 | ancestor2Len = ancestorPath2.length; 59 | 60 | // convert one of the ancestor path's into an object with key equal to the array value 61 | // and value equal to true 62 | for (i = 0; i < ancestor2Len; i += 1) { 63 | ancestor2Object[ ancestorPath2[i] ] = true; 64 | } 65 | 66 | // loop through the other ancestor path and if element is in object, return that element 67 | // else return null 68 | for (j = 0; j < ancestor1Len; j += 1) { 69 | if ( ancestor2Object[ ancestorPath1[j] ] ) { 70 | result = ancestorPath1[j]; 71 | } 72 | } 73 | 74 | return result; 75 | }; 76 | 77 | /** 78 | * should return the ancestral path of a child to this node. 79 | * more examples: 80 | * 1.) greatGrandma.getAncestorPath(me) -> [great grandma, grandma, mom, me] 81 | * 2.) mom.getAncestorPath(me) -> [mom, me] 82 | * 3.) me.getAncestorPath(me) -> [me] 83 | * 4.) grandma.getAncestorPath(H R Giger) -> null 84 | */ 85 | 86 | Tree.prototype.getAncestorPath = function (node) { 87 | var inner = function (node, result) { 88 | var self = this; 89 | var i, childPath; 90 | 91 | // always push self onto result 92 | result.push( self.name ); 93 | 94 | if ( self === node ) { 95 | return result; // array 96 | } else if ( self.children.length === 0 ) { 97 | return null; 98 | } else { 99 | for (i = 0; i < self.children.length; i += 1) { 100 | // as soon as any child is the node, return the childPath 101 | childPath = inner.call( self.children[i], node, result.slice() ); 102 | if ( childPath ) { 103 | return childPath; 104 | } 105 | } 106 | return null; 107 | } 108 | }; 109 | 110 | return inner.call(this, node, []); 111 | }; 112 | 113 | /** 114 | * check to see if the provided tree is already a child of this 115 | * tree __or any of its sub trees__ 116 | */ 117 | Tree.prototype.isDescendant = function (child) { 118 | if (this.children.indexOf(child) !== -1) { 119 | // `child` is an immediate child of this tree 120 | return true; 121 | }else{ 122 | for (var i = 0; i < this.children.length; i++) { 123 | if (this.children[i].isDescendant(child)) { 124 | // `child` is descendant of this tree 125 | return true; 126 | } 127 | } 128 | return false; 129 | } 130 | }; 131 | 132 | /** 133 | * remove an immediate child 134 | */ 135 | Tree.prototype.removeChild = function (child) { 136 | var index = this.children.indexOf(child); 137 | if(index !== -1){ 138 | // remove the child 139 | this.children.splice(index,1); 140 | }else{ 141 | throw new Error("That node is not an immediate child of this tree"); 142 | } 143 | }; 144 | -------------------------------------------------------------------------------- /commonCharacters/commonCharacters.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Write a function `f(a, b)` which takes two strings as arguments and returns a 3 | * string containing only the unique characters found in both strings, in the 4 | * order that they appeared in `a`. Remember to skip spaces and characters you 5 | * have already encountered! 6 | * 7 | * Example: commonCharacters('acexivou', 'aegihobu') 8 | * Returns: 'aeiou' 9 | * 10 | * Extra credit: Extend your function to handle more than two input strings. 11 | */ 12 | 13 | var commonCharacters = function () { 14 | var args = Array.prototype.slice.call(arguments); 15 | if (args.length < 2) throw new Error('Require at least 2 input strings'); 16 | 17 | var str = ''; 18 | var first = args[0]; 19 | 20 | /* 21 | * Key step here: keep on reducing the unique set until you get the result across 22 | * all strings 23 | */ 24 | 25 | /* 26 | * The reason createHash(first) is needed is because in order to maintain a 27 | * unique set after each reduction, you'll need to pass an initial object with 28 | * with the characters so far. If an empty object is passed, then of course there 29 | * are no other characters that will match against the empty object. 30 | */ 31 | var result = args.reduce(function (acc, cur) { 32 | return createUniqueSet(acc, cur); 33 | }, createHash(first)); 34 | 35 | for (var i = 0; i < first.length; i += 1) { 36 | if (result[first[i]]) { 37 | str += first[i]; 38 | result[first[i]] = false; 39 | } 40 | } 41 | 42 | return str; 43 | }; 44 | 45 | var createHash = function (string) { 46 | var result = {}; 47 | for (var i = 0; i < string.length; i += 1) { 48 | result[ string[i] ] = true; 49 | } 50 | return result; 51 | }; 52 | 53 | var createUniqueSet = function (obj, string) { 54 | var result = {}; 55 | var len = string.length; 56 | var i; 57 | 58 | for (i = 0; i < len; i += 1) { 59 | if (obj[ string[i] ]) { 60 | result[ string[i] ] = true; 61 | } 62 | } 63 | 64 | return result; 65 | }; -------------------------------------------------------------------------------- /constantTimeStackMin/constantTimeStackMin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Write a stack using your preferred instantiation pattern. Implement a min function 3 | * that returns the minimum value of all the elements in the stack in constant time. 4 | */ 5 | 6 | /** 7 | * Stack Class 8 | */ 9 | var Stack = function () { 10 | var storage = {}; 11 | var minSoFar = []; 12 | var top = 0; 13 | 14 | // add an item to the top of the stack 15 | this.push = function (value) { 16 | if ( minSoFar.length === 0 || value <= minSoFar[minSoFar.length - 1] ) { 17 | minSoFar.push( value ); 18 | } 19 | storage[top] = value; 20 | top += 1; 21 | }; 22 | 23 | // remove an item from the top of the stack 24 | this.pop = function () { 25 | var popped; 26 | if ( this.size() > 0) { 27 | popped = storage[top - 1]; 28 | delete storage[top - 1]; 29 | top -= 1; 30 | 31 | if ( popped === minSoFar[minSoFar.length - 1] ) { 32 | minSoFar.pop(); 33 | } 34 | return popped; 35 | } 36 | }; 37 | 38 | // return the number of items in the stack 39 | this.size = function () { 40 | return top; 41 | }; 42 | 43 | this.min = function () { 44 | return minSoFar[minSoFar.length - 1]; 45 | }; 46 | 47 | return this; 48 | }; -------------------------------------------------------------------------------- /deepEquality/deepEquality.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Write a function that, given two objects, returns whether or not the two 3 | * are deeply equivalent--meaning the structure of the two objects is the 4 | * same, and so is the structure of each of their corresponding descendants. 5 | * 6 | * Examples: 7 | * 8 | * deepEquals({a:1, b: {c:3}},{a:1, b: {c:3}}); // true 9 | * deepEquals({a:1, b: {c:5}},{a:1, b: {c:6}}); // false 10 | * 11 | * don't worry about handling cyclical object structures. 12 | * 13 | */ 14 | var deepEquals = function (apple, orange) { 15 | var isAppleArray, isOrangeArray; 16 | var appleLen, orangeLen; 17 | var appleKeys, orangeKeys; 18 | var comparison, i, prop; 19 | 20 | if ( apple === orange ) return true; 21 | if ( isPrimitive(apple) && isPrimitive(orange) ) return apple === orange; // true or false 22 | if ( isPrimitive(apple) || isPrimitive(orange) ) return false; 23 | 24 | /* 25 | * At this point: 26 | * 1) apple and orange are not identical objects 27 | * 2) neither are primitives 28 | * 3) both are objects 29 | */ 30 | 31 | isAppleArray = Array.isArray(apple); 32 | isOrangeArray = Array.isArray(orange); 33 | 34 | if ( isAppleArray && isOrangeArray ) { 35 | // apple and orange are both arrays 36 | appleLen = apple.length; 37 | orangeLen = orange.length; 38 | 39 | // break out early if neither arrays are the same length 40 | if ( appleLen !== orangeLen ) return false; 41 | 42 | for (i = 0; i < appleLen; i += 1) { 43 | comparison = deepEquals( apple[i], orange[i] ); 44 | if ( !comparison ) return false; // break out early if any comparison is not deeply equal 45 | } 46 | // reaching here implies that all items in both arrays are equal 47 | return true; 48 | } else if ( isAppleArray || isOrangeArray ) { 49 | return false; 50 | } else { 51 | // apple and orange are both objects 52 | 53 | appleKeys = Object.keys( apple ); 54 | orangeKeys = Object.keys( orange ); 55 | if ( appleKeys.length !== orangeKeys.length ) return false; 56 | 57 | for (prop in apple) { 58 | // check if prop is in orangeKeys 59 | if ( !orange[prop] ) { 60 | return false; 61 | } else { 62 | comparison = deepEquals( apple[prop], orange[prop] ); 63 | if ( !comparison ) return false; 64 | } 65 | } 66 | // reaching here implies that all the items in both objects are equal 67 | return true; 68 | } 69 | }; 70 | 71 | var isPrimitive = function (obj) { 72 | var type = typeof obj; 73 | return type === 'string' || 74 | type === 'number' || 75 | type === 'boolean' || 76 | obj === void 0 || 77 | obj === null; 78 | }; -------------------------------------------------------------------------------- /evenOccurrence/evenOccurrence.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Find the first item that occurs an even number of times in an array. 3 | * Remember to handle multiple even-occurance items and return the first one. 4 | * Return null if there are no even-occurance items. 5 | */ 6 | 7 | /* 8 | * example usage: 9 | * var onlyEven = evenOccurence([1, 7, 2, 4, 5, 6, 8, 9, 6, 4]); 10 | * console.log(onlyEven); // 4 11 | */ 12 | 13 | var evenOccurence = function (arr) { 14 | // Time Complexity: O(n) 15 | if ( !Array.isArray(arr) || arr === void 0 ) throw new Error('Need to provide an Array'); 16 | var hash = {}; 17 | var len = arr.length; 18 | var i; 19 | 20 | arr.forEach(function (num) { 21 | hash[num] = (hash[num] ? hash[num] : 0) + 1; 22 | }); 23 | 24 | for (i = 0; i < len; i += 1) { 25 | if ( hash[ arr[i] ] % 2 === 0 ) { 26 | return arr[i]; 27 | } 28 | } 29 | 30 | return null; 31 | }; 32 | -------------------------------------------------------------------------------- /eventingLibrary/eventingLibrary.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Make an eventing system mix-in that adds .trigger() and .on() to any input 3 | * object. 4 | * 5 | * Example usage: 6 | * var obj = mixEvents({ name: 'Alice', age: 30 }); 7 | * obj.on('ageChange', function(){ // On takes an event name and a callback function 8 | * console.log('Age changed'); 9 | * }); 10 | * obj.age++; 11 | * obj.trigger('ageChange'); // This should call our callback! Should log 'age changed'. 12 | * 13 | * Caveats: 14 | * - mixEvents should return the original object it was passed after extending it. 15 | * - If we repeatedly call .on with the same event name, it should 16 | * continue to call the old function as well. That is to say, we can have multiple 17 | * listeners for an event. 18 | * - If `obj.trigger` is called with additional arguments, pass those to the 19 | * listeners. 20 | * - It is not necessary to write a way to remove listeners. 21 | */ 22 | 23 | var mixEvents = function (obj) { 24 | var storage = {}; 25 | 26 | obj.on = function (eventType, callback) { 27 | if (arguments.length < 2) { 28 | throw new Error('Not enough arguments'); 29 | } 30 | 31 | if (typeof callback !== 'function') { 32 | throw new Error('Callback needs to be a function'); 33 | } 34 | 35 | // check if event already exists in storage 36 | storage[eventType] = storage[eventType] || []; 37 | storage[eventType].push(callback); 38 | }; 39 | 40 | obj.trigger = function (eventType) { 41 | if (eventType === void 0) { return; } 42 | 43 | var args = Array.prototype.slice.call(arguments, 1); 44 | var listOfCallbacks = storage[eventType] || []; 45 | 46 | listOfCallbacks.forEach(function (cb) { 47 | cb.apply(obj, args); 48 | }); 49 | }; 50 | 51 | obj.remove = function (eventType, callback) { 52 | if (arguments.length === 0) { 53 | throw new Error('Missing both arguments for remove'); 54 | } 55 | 56 | if (typeof eventType !== 'string') { 57 | throw new Error('Please pass in a string value for the event type to remove'); 58 | } 59 | 60 | storage[eventType] = storage[eventType] || []; 61 | if (arguments.length >= 2) { 62 | var i = 0; 63 | while (i < storage[eventType].length) { 64 | if (storage[eventType][i] === callback) { 65 | // remove and don't increment i 66 | storage[eventType].splice(i, 1); 67 | } else { 68 | i += 1; 69 | } 70 | } 71 | } else { 72 | // remove all callback functions associated with the event type 73 | delete storage[eventType]; 74 | } 75 | }; 76 | 77 | return obj; 78 | }; -------------------------------------------------------------------------------- /functionBind/functionBind.js: -------------------------------------------------------------------------------- 1 | /* 2 | * function bind(): 3 | * 4 | * example 1: 5 | * 6 | * var alice = { 7 | * name: 'alice', 8 | * shout: function(){ 9 | * alert(this.name); 10 | * } 11 | * } 12 | * var boundShout = bind(alice.shout, alice); 13 | * boundShout(); // alerts 'alice' 14 | * boundShout = bind(alice.shout, {name: 'bob'}); 15 | * boundShout(); // alerts 'bob' 16 | * 17 | * example 2: 18 | * 19 | * var func = function(a, b){ return a + b }; 20 | * var boundFunc = bind(func, null, 'foo'); 21 | * var result = boundFunc('bar'); 22 | * result === 'foobar'; // true 23 | * 24 | */ 25 | 26 | var bind = function (fn, context) { 27 | var outerArgs = Array.prototype.slice.call(arguments, 2); 28 | return function () { 29 | var innerArgs = Array.prototype.slice.call(arguments); 30 | var totalArgs = Array.prototype.concat( outerArgs, innerArgs ); 31 | return fn.apply(context, totalArgs); 32 | }; 33 | }; 34 | 35 | /* 36 | * Function.prototype.bind: 37 | * 38 | * example 1: 39 | * 40 | * var alice = { 41 | * name: 'alice', 42 | * shout: function(){ 43 | * alert(this.name); 44 | * } 45 | * } 46 | * var boundShout = alice.shout.bind(alice); 47 | * boundShout(); // alerts 'alice' 48 | * boundShout = alice.shout.bind({name: 'bob'}); 49 | * boundShout(); // alerts 'bob' 50 | * 51 | * example 2: 52 | * 53 | * var func = function(a, b){ return a + b }; 54 | * var boundFunc = func.bind(null, 'foo'); 55 | * var result = boundFunc('bar'); 56 | * result === 'foobar'; // true 57 | * 58 | */ 59 | 60 | Function.prototype.bind = function (context) { 61 | var fn = this; // function object 62 | var outerArgs = Array.prototype.slice.call(arguments, 1); 63 | return function () { 64 | var innerArgs = Array.prototype.slice.call(arguments); 65 | var totalArgs = Array.prototype.concat( outerArgs, innerArgs ); 66 | return fn.apply( context, totalArgs ); 67 | }; 68 | }; 69 | -------------------------------------------------------------------------------- /hashTable/hashTable.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Create a hash table with `insert()`, `retrieve()`, and `remove()` methods. 3 | * The hashtable does not need to resize but it should still handle collisions. 4 | */ 5 | 6 | var makeHashTable = function () { 7 | var result = {}; 8 | var storage = []; 9 | var storageLimit = 1000; 10 | 11 | result.insert = function (key, value) { 12 | var idx = getIndexBelowMaxForKey(key, storageLimit); 13 | var bucket = storage[idx] || []; 14 | 15 | for (var i = 0; i < bucket.length; i += 1) { 16 | // check if key, value already exists in bucket 17 | if (bucket[i][0] === key) { 18 | bucket[i][1] = value; 19 | return; 20 | } 21 | } 22 | 23 | // key, value doesn't exist in bucket 24 | bucket.push( [key, value] ); 25 | storage[idx] = bucket; 26 | }; 27 | 28 | result.retrieve = function (key) { 29 | var idx = getIndexBelowMaxForKey(key, storageLimit); 30 | var bucket = storage[idx] || []; 31 | 32 | for (var i = 0; i < bucket.length; i += 1) { 33 | if (bucket[i][0] === key) { 34 | return bucket[i][1]; 35 | } 36 | } 37 | 38 | return null; 39 | }; 40 | 41 | result.remove = function (key) { 42 | var idx = getIndexBelowMaxForKey(key, storageLimit); 43 | var bucket = storage[idx] || []; 44 | 45 | for (var i = 0; i < bucket.length; i += 1) { 46 | if (bucket[i][0] === key) { 47 | bucket.splice(i, 1); 48 | break; 49 | } 50 | } 51 | }; 52 | 53 | return result; 54 | }; 55 | 56 | // This is a "hashing function". You don't need to worry about it, just use it 57 | // to turn any string into an integer that is well-distributed between 58 | // 0 and max - 1 59 | var getIndexBelowMaxForKey = function (str, max) { 60 | var hash = 0; 61 | for (var i = 0; i < str.length; i++) { 62 | hash = (hash<<5) + hash + str.charCodeAt(i); 63 | hash = hash & hash; // Convert to 32bit integer 64 | hash = Math.abs(hash); 65 | } 66 | return hash % max; 67 | }; 68 | -------------------------------------------------------------------------------- /hashTableResizing/hashTableResizing.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Create a hash table with `insert()`, `retrieve()`, and `remove()` methods. 3 | * Be sure to handle hashing collisions correctly. 4 | * Set your hash table up to double the storage limit as 5 | * soon as the total number of items stored is greater than 6 | * 3/4th of the number of slots in the storage array. 7 | * Resize by half whenever utilization drops below 1/4. 8 | */ 9 | 10 | var makeHashTable = function () { 11 | var result = {}; 12 | var storage = []; 13 | var storageLimit = 4; 14 | var size = 0; 15 | 16 | result.insert = function (key, value) { 17 | var idx = getIndexBelowMaxForKey(key, storageLimit); 18 | var bucket = storage[idx] || []; 19 | var len = bucket.length; 20 | var utilization, i; 21 | 22 | // determine whether the key, value pair already exists as an element in bucket 23 | for ( i = 0; i < len; i += 1 ) { 24 | // if the same key already exists, replace its old value with the new one 25 | if ( bucket[i][0] === key ) { 26 | bucket[i][1] = value; 27 | return; 28 | } 29 | } 30 | 31 | // at this point, the key, value pair doesn't exist in the bucket 32 | bucket.push( [key, value] ); 33 | storage[idx] = bucket; 34 | 35 | // increase size 36 | size += 1; 37 | utilization = size / storageLimit; 38 | 39 | if ( utilization > 0.75 ) { 40 | result.adjustStorageLimit( storageLimit * 2 ); 41 | } 42 | }; 43 | 44 | result.retrieve = function (key) { 45 | var idx = getIndexBelowMaxForKey(key, storageLimit); 46 | var bucket = storage[idx] || []; 47 | var len = bucket.length; 48 | var i; 49 | 50 | for ( i = 0; i < len; i += 1 ) { 51 | if ( bucket[i][0] === key ) return bucket[i][1]; 52 | } 53 | }; 54 | 55 | result.remove = function (key) { 56 | var idx = getIndexBelowMaxForKey(key, storageLimit); 57 | var bucket = storage[idx] || []; 58 | var len = bucket.length; 59 | var utilization, value, i; 60 | 61 | for ( i = 0; i < len; i += 1 ) { 62 | if ( bucket[i][0] === key ) { 63 | value = bucket.splice(i, 1); 64 | 65 | size -= 1; 66 | utilization = size / storageLimit; 67 | 68 | if ( utilization < 0.25 ) { 69 | result.adjustStorageLimit( storageLimit / 2 ); 70 | } 71 | 72 | return value[0]; 73 | } 74 | } 75 | }; 76 | 77 | result.adjustStorageLimit = function (newStorageLimit) { 78 | // create a new storage array 79 | var newStorageArray = []; 80 | var newBucket, idx; 81 | 82 | // for each bucket in current storage array 83 | storage.forEach(function (bucket) { 84 | bucket.forEach(function (array) { 85 | // re-hash all key, value pairs and push them into newStorageArray 86 | idx = getIndexBelowMaxForKey( array[0], newStorageLimit ); 87 | newBucket = newStorageArray[idx] || []; 88 | newBucket.push( [ array[0], array[1] ] ); 89 | newStorageArray[idx] = newBucket; 90 | }); 91 | }); 92 | 93 | // set storage array as new storage array 94 | storage = newStorageArray; 95 | // set storage limit as new storage limit 96 | storageLimit = newStorageLimit; 97 | }; 98 | 99 | return result; 100 | }; 101 | 102 | // This is a "hashing function". You don't need to worry about it, just use it 103 | // to turn any string into an integer that is well-distributed between 104 | // 0 and max - 1 105 | var getIndexBelowMaxForKey = function (str, max) { 106 | var hash = 0; 107 | for (var i = 0; i < str.length; i++) { 108 | hash = (hash<<5) + hash + str.charCodeAt(i); 109 | hash = hash & hash; // Convert to 32bit integer 110 | hash = Math.abs(hash); 111 | } 112 | return hash % max; 113 | }; 114 | -------------------------------------------------------------------------------- /htmljQueryColor/README.md: -------------------------------------------------------------------------------- 1 | ## HTML/jQuery 2 | The included index.html contains two paragraph tags, each containing a block of lorem ipsum text. Using the file `main.js`: 3 | * [ ] Write a function that wraps every word in its own `` tag. 4 | * [ ] Make each word change color once per second to a random color. 5 | 6 | -------------------------------------------------------------------------------- /htmljQueryColor/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |

9 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 10 |

11 | 12 |

13 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 14 |

15 | 16 | 17 | -------------------------------------------------------------------------------- /htmljQueryColor/main.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | // --------------STEP 1-------------- 3 | // wrap every word in every `

` tag with a `` tag. 4 | // for example:

Hey there

5 | // becomes:

Heythere

6 | // HINT: the `split` array method is your friend 7 | 8 | var addSpan = function () { 9 | $('p').each(function (idx, p) { 10 | var $pElement = $(p); 11 | 12 | var text = $pElement.text().trim().split(' ').reduce(function (acc, cur) { 13 | return acc + '' + cur + '' + ' '; 14 | }, ''); 15 | 16 | $pElement.html( text ); 17 | }); 18 | }; 19 | 20 | // --------------STEP 2-------------- 21 | // Next, change spans to random colors, once per second 22 | 23 | var changeSpanColors = function () { 24 | $('span').each(function (idx, s) { 25 | var r = Math.floor( Math.random() * 256 ); 26 | var g = Math.floor( Math.random() * 256 ); 27 | var b = Math.floor( Math.random() * 256 ); 28 | var rgb = 'rgb(' + r + ', ' + g + ', ' + b + ')'; 29 | $(s).css( 'background-color', rgb ); 30 | }); 31 | }; 32 | 33 | addSpan(); 34 | setInterval(changeSpanColors, 1000); 35 | }); -------------------------------------------------------------------------------- /implementingOperators/implementingOperators.js: -------------------------------------------------------------------------------- 1 | // Implement multiply, divide, and modulo using only the addition and 2 | // subtraction operators. start off my assuming all inputs are integers 3 | // 4 | // Step 2: Make divide produce answers to three decimal places 5 | // (e.g. 2/3 => 0.667). 6 | // 7 | // Extra credit: Make multiply work with decimals 8 | // (e.g. multiply(2.5, 10.2) 9 | // 10 | // Terror mode: Re-implement all three functions using only bitwise operators. 11 | 12 | 13 | var multiply = function(x, y) { 14 | // TODO: should return the product of x * y 15 | }; 16 | 17 | var divide = function(x, y) { 18 | // TODO: should return the dividend of x / y 19 | }; 20 | 21 | var modulo = function(x, y) { 22 | // TODO: should return the remainder of x / y 23 | }; 24 | 25 | 26 | -------------------------------------------------------------------------------- /insertionSort/insertionSort.js: -------------------------------------------------------------------------------- 1 | /*jshint expr:true*/ 2 | 3 | /** 4 | * Insertion sort is another basic sorting algorithm. Insertion sort 5 | * iterates over an array, growing a sorted array behind the current location. 6 | * It takes each element from the input and finds the spot, up to the current point, 7 | * where that element belongs. It does this until it gets to the end of the array. 8 | **/ 9 | 10 | // Example usage: 11 | // insertionSort([2, 1, 3]); // yields [1, 2, 3] 12 | 13 | var insertionSort = function (array) { 14 | var length = array.length; 15 | var i, j, hole; 16 | 17 | if (length < 2) { return array; } 18 | for (i = 1; i < length; i += 1) { 19 | hole = array[i]; 20 | j = i; 21 | while (j > 0 && array[j - 1] > hole) { 22 | array[j] = array[j - 1]; 23 | j -= 1; 24 | } 25 | array[j] = hole; 26 | } 27 | 28 | return array; 29 | }; 30 | -------------------------------------------------------------------------------- /isSubsetOf/isSubsetOf.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Make an array method that can return whether or not a context array is a 3 | * subset of an input array. To simplify the problem, you can assume that both 4 | * arrays will contain only strings. 5 | * 6 | * See http://en.wikipedia.org/wiki/Subset for more on the definition of a 7 | * subset. 8 | */ 9 | 10 | /* 11 | * Extra credit: Make the method work for arrays that contain any value, 12 | * including non-strings. 13 | */ 14 | 15 | Array.prototype.isSubsetOf = function (array) { 16 | var subset = this; 17 | var subsetLen = subset.length; 18 | var supersetLen = array.length; 19 | var first, found; 20 | 21 | // base case 22 | if ( subsetLen > supersetLen ) return false; 23 | if ( subsetLen === 0 && supersetLen >= 0 ) return true; 24 | 25 | // supLen is greater than or equal to subLen and supLen is greater than 0 26 | first = subset[0]; 27 | found = array.indexOf( first ); 28 | 29 | if ( found === -1 ) return false; 30 | return subset.slice(1).isSubsetOf( Array.prototype.concat( array.slice(0, found), array.slice(found + 1) ) ); 31 | }; -------------------------------------------------------------------------------- /jsonpFetcher/jsonpFetcher.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | JSONParty 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /jsonpFetcher/jsonpFetcher.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implement a function that takes a URL and a callback and makes a JSONP 3 | * GET request to that URL. 4 | * 5 | * We've provided the following API endpoint: 6 | * http://toy-problems.hackreactor.com/jsonparty 7 | * 8 | * Your function should accept a call with that URL, and call the callback 9 | * with the response data from the server. You should NOT return the response 10 | * from the server, only the wrapped data! jQuery is not available, and you won't 11 | * be able to do this using a native XMLHttpRequest. 12 | * 13 | * Example: 14 | * jsonpRequest('http://toy-problems.hackreactor.com/jsonparty', function (data) { 15 | * console.log(data.response); // "Aw yeah, now we're JSONPartying" 16 | * console.log(data.random); // 3558 17 | * }); 18 | * 19 | * // Subsequent requests should have properly random responses: 20 | * jsonpRequest('http://toy-problems.hackreactor.com/jsonparty', function (data) { 21 | * console.log(data.random); // 1733 22 | * }); 23 | * 24 | * Hint: The API accepts a `callback` parameter. What is that for? 25 | * See http://en.wikipedia.org/wiki/JSONP if you need more information 26 | * about this exciting AJAX protocol! 27 | * 28 | */ 29 | 30 | var jsonpRequest = function(url, callback) { 31 | }; 32 | -------------------------------------------------------------------------------- /key-concepts.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Write a function that generates every sequence of throws a single 3 | * player could throw over a three-round game of rock-paper-scissors. 4 | * 5 | * Example: 6 | * [ 7 | * [ // one possible three round game outcome 8 | * 'rock', // round 1 9 | * 'paper', // round 2 10 | * 'scissors' // round 3 11 | * ], 12 | * [ // next possible three round game outcome 13 | * 'rock', // round 1 14 | * 'paper', // round 2 15 | * 'rock' // round 3 16 | * ], 17 | * etc... 18 | * ] 19 | * 20 | * Extra credit: Make your function return answers for any number of rounds. 21 | * 22 | * Example: 23 | * rockPaperScissors(5); // => [['rock', 'rock', 'rock', 'rock', 'rock'], etc...] 24 | */ 25 | 26 | /* 27 | * Key Concepts: recursion, head recursion, returning a copy of array 28 | */ 29 | var rockPaperScissors = function (num) { 30 | var previous, possibleThrow; 31 | 32 | // establish base cases 33 | if (num <= 0) return []; 34 | if (num === 1) return [ ['rock'], ['paper'], ['scissors'] ]; 35 | 36 | // recursive case 37 | possibleThrow = ['rock', 'paper', 'scissors']; 38 | previous = rockPaperScissors(num - 1); // assume num - 1 solution is solved 39 | 40 | /* 41 | * Go through each array solution in previous and add each possible throw onto 42 | * that particular solution, and then append the new throw to result. 43 | */ 44 | 45 | return previous.reduce(function (acc, soFar) { 46 | possibleThrow.forEach(function (hand) { 47 | acc.push( soFar.concat(hand) ); 48 | }); 49 | return acc; 50 | }, []); 51 | }; 52 | 53 | /* 54 | * Given an array of values, produce all permutations of those values. 55 | */ 56 | 57 | /* 58 | * Key Concepts: recursion, head recursion, returning a copy of array 59 | */ 60 | var permutations = function (array) { 61 | var len = array.length; 62 | var first, rest, previous; 63 | 64 | // establish base cases 65 | if (len === 0) return []; 66 | if (len === 1) return [ array ]; 67 | 68 | // recursive case 69 | first = array.slice(0, 1); 70 | rest = array.slice(1); 71 | previous = permutations( rest ); // assume permutations of the original array excluding the first element has been solved 72 | 73 | /* 74 | * Go through each array in previous, and for each array, concatenate the first 75 | * array into each index from 0 to end of that array. Append the resultant array 76 | * into result. 77 | */ 78 | return previous.reduce(function (acc, soFar) { 79 | var i, temp; 80 | for (i = 0; i <= soFar.length; i += 1) { 81 | temp = Array.prototype.concat( soFar.slice(0, i), first, soFar.slice(i) ); 82 | acc.push( temp ); 83 | } 84 | return acc; 85 | }, []); 86 | }; 87 | 88 | /* 89 | * Given an array of values, produce an array of all the combinations of those values. 90 | */ 91 | 92 | /* 93 | * Key Concepts: recursion, head recursion, returning a copy of array 94 | */ 95 | var combinations = function (array) { 96 | var len = array.length; 97 | var first, rest, previous, result; 98 | 99 | // establish base cases 100 | if (len === 0) return []; 101 | if (len === 1) return [ array ]; 102 | 103 | // recursive case 104 | result = []; 105 | first = array.slice(0, 1); 106 | rest = array.slice(1); 107 | previous = combinations( rest ); 108 | 109 | /* 110 | * For each array in previous, append 2 copies: one of the array itself and 111 | * another of the array with the first value concatenated to it. Also append 112 | * the first value itself onto result. 113 | */ 114 | 115 | previous.forEach(function (soFar) { 116 | result.push( soFar ); 117 | result.push( first.concat(soFar) ); 118 | }); 119 | 120 | result.push( first ); 121 | return result; 122 | }; 123 | 124 | /* 125 | * Given a sorted array, perform binary search 126 | */ 127 | 128 | /* 129 | * Key Concepts: array indices, recursion, O(log n) 130 | */ 131 | var binarySearch = function (sortedArray, value) { 132 | var len = sortedArray.length; 133 | var inner = function (start, end) { 134 | var mid = Math.floor( (start + end) / 2 ); 135 | 136 | // base cases 137 | if (mid === start || mid === end) return sortedArray[mid] === value ? mid : null; 138 | if (value === sortedArray[mid]) return mid; 139 | 140 | // recursive case 141 | if (value < sortedArray[mid]) return inner(start, mid); 142 | return inner(mid, end); 143 | }; 144 | 145 | return inner(0, len); 146 | }; 147 | 148 | /* 149 | * Make an array method that can return whether or not a context array is a 150 | * subset of an input array. To simplify the problem, you can assume that both 151 | * arrays will contain only strings. 152 | * 153 | * See http://en.wikipedia.org/wiki/Subset for more on the definition of a 154 | * subset. 155 | */ 156 | 157 | /* 158 | * Extra credit: Make the method work for arrays that contain any value, 159 | * including non-strings. 160 | */ 161 | 162 | /* 163 | * Key Concepts: gain efficiency by converting to hash table O(n) 164 | */ 165 | var isSubsetOf = function (base, input) { 166 | var baseHash = {}; 167 | var inputHash = {}; 168 | var prop; 169 | 170 | base.forEach(function (i) { 171 | baseHash[i] = baseHash[i] || 0; 172 | baseHash[i] += 1; 173 | }); 174 | 175 | input.forEach(function (i) { 176 | inputHash[i] = inputHash[i] || 0; 177 | inputHash[i] += 1; 178 | }); 179 | 180 | for (prop in inputHash) { 181 | // prop doesn't show up in baseHash 182 | if (!baseHash[prop]) return false; 183 | 184 | // the amount in inputHash > baseHash 185 | baseHash[prop] = baseHash[prop] - inputHash[prop]; 186 | if (baseHash[prop] < 0) return false; 187 | } 188 | 189 | return true; 190 | }; 191 | 192 | /* 193 | * In England the currency is made up of pound, £, and pence, p, and there are eight coins in general circulation: 194 | * 195 | * 1p piece 196 | * 2p piece 197 | * 5p piece 198 | * 10p piece 199 | * 20p piece 200 | * 50p piece 201 | * 1 euro (100p) 202 | * 2 euro (200p) 203 | * 204 | * It is possible to make £2 in the following way: 205 | * 206 | * 1 * £1 + 1 * 50p + 2 * 20p + 1 * 5p + 1 * 2p + 3 * 1p 207 | * How many different ways can £2 be made using any number of coins? 208 | * 209 | * Example usage of `makeChange`: 210 | * 211 | * There's only one way to make 1p. that's with a single 1p piece 212 | * makeChange(1) === 1 213 | * 214 | * There's only two ways to make 2p. that's with two, 1p pieces or with a single 2p piece 215 | * makeChange(2) === 2 216 | */ 217 | 218 | /* 219 | * Key Concepts: using reduce for recursion, recursion, tail recursion, creating placeholder functions 220 | */ 221 | var makeChange = function (amt) { 222 | var inner = function (amt, coins) { 223 | // establish base cases 224 | if (amt < 0) return 0; 225 | if (amt === 0) return 1; 226 | 227 | // recursive case 228 | /* 229 | * For the given amt, find the available coins that can be used. 230 | * For each of those coins, return the accumulated sum of inner with the 231 | * amt reduced by the coin used and available coins equal to coin amt. 232 | */ 233 | return coins.reduce(function (total, eachCoin) { 234 | return total + inner(amt - eachCoin, availableCoins(eachCoin)); 235 | }, 0); 236 | }; 237 | 238 | return inner(amt, availableCoins(amt)); 239 | }; 240 | 241 | var availableCoins = function (amt) { 242 | return [200, 100, 50, 20, 10, 5, 2, 1].filter(function (value) { 243 | return amt >= value; 244 | }); 245 | }; 246 | 247 | /* 248 | * Make an eventing system mix-in that adds .trigger() and .on() to any input 249 | * object. 250 | * 251 | * Example usage: 252 | * var obj = mixEvents({ name: 'Alice', age: 30 }); 253 | * obj.on('ageChange', function(){ // On takes an event name and a callback function 254 | * console.log('Age changed'); 255 | * }); 256 | * obj.age++; 257 | * obj.trigger('ageChange'); // This should call our callback! Should log 'age changed'. 258 | * 259 | * Caveats: 260 | * - mixEvents should return the original object it was passed after extending it. 261 | * - If we repeatedly call .on with the same event name, it should 262 | * continue to call the old function as well. That is to say, we can have multiple 263 | * listeners for an event. 264 | * - If `obj.trigger` is called with additional arguments, pass those to the 265 | * listeners. 266 | * - It is not necessary to write a way to remove listeners. 267 | */ 268 | 269 | /* 270 | * Key Concepts: closure, arguments, caching, lexical scope 271 | */ 272 | var mixEvents = function (obj) { 273 | var eventCache = {}; 274 | 275 | obj.on = function (ev, callback) { 276 | eventCache[ev] = eventCache[ev] || []; 277 | eventCache[ev].push( callback ); 278 | }; 279 | 280 | obj.trigger = function (ev) { 281 | var args = Array.prototype.slice.call(arguments, 1); 282 | eventCache[ev].forEach(function (callback) { 283 | callback.apply(this, args); 284 | }); 285 | }; 286 | 287 | return obj; 288 | }; 289 | 290 | /* 291 | * function bind(): 292 | * 293 | * example 1: 294 | * 295 | * var alice = { 296 | * name: 'alice', 297 | * shout: function(){ 298 | * alert(this.name); 299 | * } 300 | * } 301 | * var boundShout = bind(alice.shout, alice); 302 | * boundShout(); // alerts 'alice' 303 | * boundShout = bind(alice.shout, {name: 'bob'}); 304 | * boundShout(); // alerts 'bob' 305 | * 306 | * example 2: 307 | * 308 | * var func = function(a, b){ return a + b }; 309 | * var boundFunc = bind(func, null, 'foo'); 310 | * var result = boundFunc('bar'); 311 | * result === 'foobar'; // true 312 | * 313 | */ 314 | 315 | /* 316 | * Key Concepts: arguments (not an Array), returning functions, closures, context 317 | */ 318 | var bind = function (fn, context) { 319 | var outerArgs = Array.prototype.slice.call(arguments, 2); 320 | return function () { 321 | var innerArgs = Array.prototype.slice.call(arguments); 322 | var allArgs = Array.prototype.concat(outerArgs, innerArgs); 323 | return fn.apply(context, allArgs); 324 | }; 325 | }; 326 | 327 | /* 328 | * Write a function that takes as its input a string and returns an array of 329 | * arrays as shown below sorted in descending order by frequency and then by 330 | * ascending order by character. 331 | * 332 | * 333 | * :: Example :: 334 | * 335 | * characterFrequency('mississippi') === 336 | * [ 337 | * ['i', 4], 338 | * ['s', 4], 339 | * ['p', 2], 340 | * ['m', 1] 341 | * ] 342 | * 343 | * :: Gotcha :: 344 | * 345 | * characterFrequency('miaaiaaippi') === 346 | * [ 347 | * ['a', 4], 348 | * ['i', 4], 349 | * ['p', 2], 350 | * ['m', 1] 351 | * ] 352 | * 353 | * 354 | */ 355 | 356 | /* 357 | * Key Concepts: quick sort O(n * log(n)), converting to hash 358 | */ 359 | var characterFrequency = function (string) { 360 | return arrayOfArray( convertToHash(string) ).sort(function (arr1, arr2) { 361 | if (arr1[1] > arr2[1]) { 362 | return -1; 363 | } else if (arr1[1] < arr2[1]) { 364 | return 1; 365 | } else { 366 | // arr1[1] === arr2[1] 367 | return arr1[0] < arr2[0] ? -1 : 1; 368 | } 369 | }); 370 | }; 371 | 372 | var convertToHash = function (string) { 373 | var hash = {}; 374 | for (var i = 0; i < string.length; i += 1) { 375 | hash[ string[i] ] = hash[ string[i] ] || 0; 376 | hash[ string[i] ] += 1; 377 | } 378 | return hash; 379 | }; 380 | 381 | var arrayOfArray = function (obj) { 382 | var result = []; 383 | for (var prop in obj) { 384 | result.push( [prop, obj[prop]] ); 385 | } 386 | return result; 387 | }; 388 | 389 | /* 390 | * Anagram Detection 391 | * 392 | * Write a function that accepts two parameters, a parent and a child string. 393 | * Determine how many times the child string - or an anagram of the of the child 394 | * string - appears in the parent string. There is a solution which can be done 395 | * in near instant time. 396 | * 397 | * f('AdnBndAndBdaBn', 'dAn') // 4 ("Adn", "ndA", "dAn", "And") 398 | * f('AbrAcadAbRa', 'cAda') // 2 399 | */ 400 | 401 | /* 402 | * Key Concepts: functional programming, all numbers of products of prime numbers 403 | */ 404 | var numAnagrams = function (base, child) { 405 | var childLen = child.length; 406 | var baseLen = base.length; 407 | var count = 0; 408 | var slice, start, end; 409 | 410 | for (start = 0; start < baseLen - childLen; start += 1) { 411 | for (end = start + childLen; end < baseLen; end += 1) { 412 | slice = base.slice(start, end); 413 | if (isAnagram(slice, child)) { 414 | count += 1; 415 | } 416 | } 417 | } 418 | return count; 419 | }; 420 | 421 | var isAnagram = function () { 422 | var args = Array.prototype.slice.call(arguments); 423 | var values = args.map(function (arg) { 424 | return convertToValue(arg); 425 | }); 426 | 427 | return values.reduce(function (a, c) { 428 | return a && c === values[0]; 429 | }, true); 430 | }; 431 | 432 | var convertToValue = function (string) { 433 | return string.split('').reduce(function (a, c) { 434 | return a * characterToPrime[c]; 435 | }, 1); 436 | }; 437 | 438 | var characterToPrime = { 439 | a: 2, 440 | b: 3, 441 | c: 5, 442 | d: 7, 443 | e: 11, 444 | f: 13, 445 | g: 17, 446 | h: 19, 447 | i: 23, 448 | j: 29, 449 | k: 31, 450 | l: 37, 451 | m: 41, 452 | n: 43, 453 | o: 47, 454 | p: 53, 455 | q: 59, 456 | r: 61, 457 | s: 67, 458 | t: 71, 459 | u: 73, 460 | v: 79, 461 | w: 83, 462 | x: 89, 463 | y: 97, 464 | z: 101, 465 | A: 103, 466 | B: 107, 467 | C: 109, 468 | D: 113, 469 | E: 127, 470 | F: 131, 471 | G: 137, 472 | H: 139, 473 | I: 149, 474 | J: 151, 475 | K: 157, 476 | L: 163, 477 | M: 167, 478 | N: 173, 479 | O: 179, 480 | P: 181, 481 | Q: 191, 482 | R: 193, 483 | S: 197, 484 | T: 199, 485 | U: 211, 486 | V: 223, 487 | W: 227, 488 | X: 229, 489 | Y: 233, 490 | Z: 239 491 | }; 492 | 493 | /* 494 | * Binary Search Tree Check 495 | * 496 | * Given a binary tree, check whether it’s a binary search tree or not. 497 | */ 498 | 499 | /* 500 | * Key Concept: recursion 501 | */ 502 | var isBinarySearchTree = function (node) { 503 | var inner = function (node, lowerbound, upperbound) { 504 | // base case 505 | if (!node) return true; 506 | 507 | var value = node.value; 508 | return (lowerbound <= value && value < upperbound) ? 509 | inner(node.left, min, value) && inner(node.right, value, max) : 510 | false; 511 | }; 512 | 513 | return inner(node, Math.MIN_VALUE, Math.MAX_VALUE); 514 | }; 515 | 516 | /* 517 | * Array Pair Sum 518 | * 519 | * Given an integer array, output all pairs that sum up to a specific value k. 520 | * Consider the fact that the same number can add up to `k` with its duplicates 521 | * in the array. For example the array is [1, 1, 2, 3, 4] and the desired sum 522 | * is 4. Should we output the pair (1, 3) twice or just once? Also do we output 523 | * the reverse of a pair, meaning both (3, 1) and (1, 3)? Let’s keep the output 524 | * as short as possible and print each pair only once. So, we will output only 525 | * one copy of (1, 3). Also note that we shouldn’t output (2, 2) because it’s 526 | * not a pair of two distinct elements. 527 | * 528 | * Example 529 | * f(10, [3, 4, 5, 6, 7]) // [ [6, 4], [7, 3] ] 530 | * f(8, [3, 4, 5, 4, 4]) // [ [3, 5], [4, 4], [4, 4], [4, 4] ] 531 | * 532 | * Source 533 | * http://www.ardendertat.com/2011/09/17/programming-interview-questions-1-array-pair-sum/ 534 | */ 535 | 536 | var arrayPairSum = function (num, array) { 537 | var hash = {}; 538 | var result = []; 539 | var matchPairs = createAllPairs(array).filter(function (arr) { 540 | return arr.reduce(function (a, c) { return a + c; }, 0) === num; 541 | }); 542 | 543 | matchPairs.forEach(function (pair) { 544 | hash[ pair ] = hash[ pair ] || hash[ pair.reverse() ] || true; 545 | }); 546 | 547 | for (var prop in hash) { 548 | var temp = prop.split(','); 549 | result.push( [ parseInt(temp[0], 10), parseInt(temp[1], 10) ] ); 550 | } 551 | return result; 552 | }; 553 | 554 | var createAllPairs = function (array) { 555 | var len = array.length; 556 | var result = []; 557 | var i, j; 558 | 559 | for (i = 0; i < len - 1; i += 1) { 560 | for (j = i + 1; j < len; j += 1) { 561 | result.push( [array[i], array[j]] ); 562 | } 563 | } 564 | return result; 565 | }; 566 | 567 | /* 568 | * Find Even Occurring Element 569 | * 570 | * Given an integer array, one element occurs even number of times and all 571 | * others have odd occurrences. Find the element with even occurrences. 572 | */ 573 | 574 | /* 575 | * Key Concepts: creating hashes for constant time lookup 576 | */ 577 | var evenOccurences = function (integerArray) { 578 | var len = integerArray.length; 579 | var hash = integerHash(integerArray); 580 | 581 | for (var i = 0; i < len; i += 1) { 582 | if (hash[ integerArray[i] ] % 2 === 0) return integerArray[i]; 583 | } 584 | 585 | throw new Error('There are no even occurrences'); 586 | }; 587 | 588 | var integerHash = function (integerArray) { 589 | var hash = {}; 590 | for (var i = 0; i < integerArray.length; i += 1) { 591 | hash[ integerArray[i] ] = hash[ integerArray[i] ] || 0; 592 | hash[ integerArray[i] ] += 1; 593 | } 594 | return hash; 595 | }; 596 | 597 | /* 598 | * Flatten Array 599 | * 600 | * Write a function that accepts a multi dimensional array and returns a 601 | * flattened version. 602 | * 603 | * flatten([1, 2, [3, [4], 5, 6], 7]) // [1, 2, 3, 4, 5, 6, 7] 604 | */ 605 | 606 | /* 607 | * Key Concepts: recursion, tail recursion, concat producing new array value 608 | */ 609 | var flatten = function (array) { 610 | var len = array.length; 611 | var first, rest; 612 | 613 | // establish base case 614 | if (len === 0) return array; 615 | 616 | // recursive case 617 | first = array[0]; 618 | rest = array.slice(1); 619 | 620 | return Array.isArray(first) ? 621 | flatten(first).concat( flatten(rest) ) : 622 | Array.prototype.concat( first, flatten(rest) ); 623 | }; 624 | 625 | /* 626 | * Integer Difference 627 | * 628 | * Write a function that accepts an array of random integers and an integer *n*. 629 | * Determine the number of times where two integers in the array have the 630 | * difference of *n*. 631 | * 632 | * f(4, [1, 1, 5, 6, 9, 16, 27]) // 3 (Due to 2x [1, 5], and [5, 9]) 633 | * f(2, [1, 1, 3, 3]) // 4 (Due to 4x [1, 3]) 634 | */ 635 | 636 | /* 637 | * Key Concepts: iterative approach 638 | */ 639 | var integerDifference = function (num, array) { 640 | var len = array.length; 641 | var count = 0; 642 | var i, j; 643 | 644 | for (i = 0; i < len - 1; i += 1) { 645 | for (j = i + 1; j < len; j += 1) { 646 | if (Math.abs( array[i] - array[j] ) === num) { 647 | count += 1; 648 | } 649 | } 650 | } 651 | 652 | return count; 653 | }; 654 | 655 | /* 656 | * Largest Palindrome 657 | * 658 | * Write a function that finds the largest palindrome in a string. All 659 | * characters can be valid for the palindrome, including whitespace. In the 660 | * string "I am a red racecar driver" - the largest palindrome would be 661 | * "d racecar d". 662 | */ 663 | 664 | /* 665 | * Key Concepts: iterative approach 666 | */ 667 | var largestPalindrome = function (string) { 668 | var len = string.length; 669 | var maxLength = 0; 670 | var result = ''; 671 | var start, end, slice; 672 | 673 | for (start = 0; start < len - 1; start += 1) { 674 | for (end = start + 1; end < len; end += 1) { 675 | // create slices of the string and check if each slice is a palindrome 676 | // if it is, check if its the largest palindrome so far 677 | slice = string.slice(start, end); 678 | if (isPalindrome(slice) && slice.length > maxLength) { 679 | result = slice; 680 | maxLength = slice.length; 681 | } 682 | } 683 | } 684 | return result; 685 | }; 686 | 687 | var isPalindrome = function (string) { 688 | return string === string.split('').reverse().join(''); 689 | }; 690 | 691 | /* 692 | * Longest Words 693 | * 694 | * Write a function that returns the longest word(s) from a sentence. The 695 | * function should not return any duplicate words (case-insensitive). 696 | * 697 | * longestWords("You are just an old antidisestablishmentarian") 698 | * => ["antidisestablishmentarian"] 699 | * longestWords("I gave a present to my parents") => ["present", "parents"] 700 | * longestWords("Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo 701 | * buffalo") => ["buffalo"] or ["Buffalo"] 702 | */ 703 | 704 | /* 705 | * Key Concepts: functional programming, creating hash tables 706 | */ 707 | var longestWords = function (string) { 708 | // convert string to array of words 709 | var words = reduceWords( string.toLowerCase().split(' ') ); 710 | 711 | // convert array of words to array of word lengths 712 | // apply Max on array of word lengths 713 | var max = Math.max.apply(null, words.map(function (word) { 714 | return word.length; 715 | })); 716 | 717 | // return words with length equal to max length 718 | return words.filter(function (word) { 719 | return word.length === max; 720 | }); 721 | }; 722 | 723 | var reduceWords = function (array) { 724 | var hash = {}; 725 | for (var i = 0; i < array.length; i += 1) { 726 | hash[ array[i] ] = hash[ array[i] ] || true; 727 | } 728 | return Object.keys(hash); 729 | }; 730 | 731 | /* 732 | * Once 733 | * 734 | * Write a function that accepts a function as it's only argument and returns a 735 | * new function that can only ever be executed once. 736 | * 737 | * Once completed, add a second arguments that allows the function to be 738 | * executed `x` number of times before it stops working. 739 | */ 740 | 741 | /* 742 | * Key Concepts: closure, lexical scope, returning functions as values, arguments 743 | */ 744 | var once = function (fn, x) { 745 | x = x || 1; 746 | var counter = 0; 747 | return function () { 748 | var args = Array.prototype.slice.call(arguments); 749 | if (counter < x) { 750 | counter += 1; 751 | return fn.apply(this, args); 752 | } 753 | }; 754 | }; 755 | 756 | /* 757 | * Get Elements by Class Name 758 | * Implement the `getElementsByClassName(element, className)` function in Javascript 759 | */ 760 | 761 | var getElementsByClassName = function (className, element) { 762 | element = element || document.body; 763 | 764 | var inner = function (node, result) { 765 | // check if current node has the class name 766 | if (node.className.split(' ').indexOf(className) !== -1) { 767 | // if it does, add the current node to result 768 | result.push( node ); 769 | } 770 | 771 | // determine whether current node has children 772 | var children = Array.prototype.slice.call(node.children); 773 | // if it doesn't then return result 774 | // if it does: 775 | // for each child, invoke inner on the child and a new empty array 776 | // the returned value will be an array which should be concatenated to 777 | // the current scope's result array 778 | 779 | return children.reduce(function (acc, child) { 780 | return result.concat( inner(child, []) ); 781 | }, result); 782 | }; 783 | 784 | return inner(element, []); 785 | }; 786 | 787 | /* 788 | * Assignment: Write a function that returns true if a linked list contains a cycle, or false if it terminates somewhere 789 | * 790 | * Explanation: 791 | * 792 | * Generally, we assume that a linked list will terminate in a null next pointer, as follows: 793 | * 794 | * A -> B -> C -> D -> E -> null 795 | * 796 | * A 'cycle' in a linked list is when traversing the list would result in visiting the same nodes over and over 797 | * This is caused by pointing a node in the list to another node that already appeared earlier in the list. Example: 798 | * 799 | * A -> B -> C 800 | * ^ | 801 | * | v 802 | * E <- D 803 | * 804 | * Example code: 805 | * 806 | * var nodeA = Node('A'); 807 | * var nodeB = nodeA.next = Node('B'); 808 | * var nodeC = nodeB.next = Node('C'); 809 | * var nodeD = nodeC.next = Node('D'); 810 | * var nodeE = nodeD.next = Node('E'); 811 | * hasCycle(nodeA); // => false 812 | * nodeE.next = nodeB; 813 | * hasCycle(nodeA); // => true 814 | * 815 | * Constraint 1: Do this in linear time 816 | * Constraint 2: Do this in constant space 817 | * Constraint 3: Do not mutate the original nodes in any way 818 | */ 819 | 820 | var hasCycle = function (node) { 821 | var first = node; 822 | var second = node; 823 | 824 | while (first && second) { 825 | if (first === second) return true; 826 | 827 | first = node.next; 828 | second = node.next.next; 829 | } 830 | 831 | return false; 832 | }; -------------------------------------------------------------------------------- /key-concepts.rb: -------------------------------------------------------------------------------- 1 | # 2 | # write a function that takes a string of text and returns true if 3 | # the parentheses are balanced and false otherwise. 4 | # 5 | # Example: 6 | # balanced_parens('('); // false 7 | # balanced_parens('()'); // true 8 | # balanced_parens(')('); // false 9 | # balanced_parens('(())'); // true 10 | # 11 | # Step 2: 12 | # make your solution work for all types of brackets 13 | # 14 | # Example: 15 | # balanced_parens('[](){}'); // true 16 | # balanced_parens('[({})]'); // true 17 | # balanced_parens('[(]{)}'); // false 18 | # 19 | # Step 3: 20 | # ignore non-bracket characters 21 | # balanced_parens(' var wow = { yo: thisIsAwesome() }'); // true 22 | # balanced_parens(' var hubble = function() { telescopes.awesome();'); // false 23 | # 24 | 25 | # Key Concepts: 26 | # When resolving an identifier, if the identifier is a local variable, then 27 | # check whether the current scope has it. If not, then an error will be thrown. 28 | # If the identifier is not a keyword, then it will be an implicit method call 29 | # to the 'self' object. 30 | 31 | def balanced_parens(string) 32 | stack = [] 33 | matching_character = { ')' => '(', ']' => '[', '}' => '{' } 34 | 35 | string.each_char do |char| 36 | if is_opening_character(char) 37 | stack.push(char) 38 | elsif is_closing_character(char) 39 | remove = stack.pop 40 | return false if matching_character[char] != remove 41 | end 42 | end 43 | 44 | return stack.length == 0 45 | end 46 | 47 | def is_opening_character(character) 48 | character == '(' || character == '[' || character == '{' 49 | end 50 | 51 | def is_closing_character(character) 52 | character == ')' || character == ']' || character == '}' 53 | end 54 | 55 | # 56 | # Write a function `f(a, b)` which takes two strings as arguments and returns a 57 | # string containing only the unique characters found in both strings, in the 58 | # order that they appeared in `a`. Remember to skip spaces and characters you 59 | # have already encountered! 60 | # 61 | # Example: common_characters('acexivou', 'aegihobu') 62 | # Returns: 'aeiou' 63 | # 64 | # Extra credit: Extend your function to handle more than two input strings. 65 | # 66 | 67 | # def common_characters(a, b) 68 | # require 'set' 69 | # 70 | # result = '' 71 | # set_a = Set.new a.split('') 72 | # set_b = Set.new b.split('') 73 | # intersect = set_a & set_b 74 | # 75 | # set_a.each do |char| 76 | # result += char if intersect.include? char 77 | # end 78 | # 79 | # result 80 | # end 81 | 82 | def common_characters(a, b) 83 | hash_a = create_hash_from_string(a) 84 | hash_b = create_hash_from_string(b) 85 | intersect = in_common_hash(hash_a, hash_b) 86 | 87 | result = '' 88 | hash_a.each do |key, value| 89 | result += key if intersect[key] 90 | end 91 | result 92 | end 93 | 94 | def create_hash_from_string(string) 95 | hash = {} 96 | string.each_char do |char| 97 | hash[char] ||= true 98 | end 99 | hash 100 | end 101 | 102 | def in_common_hash(hash_one, hash_two) 103 | result = {} 104 | hash_one.each do |key, value| 105 | result[key] = true if hash_two[key] 106 | end 107 | result 108 | end 109 | 110 | # 111 | # Write a function that generates every sequence of throws a single 112 | # player could throw over a three-round game of rock-paper-scissors. 113 | # 114 | # Example: 115 | # [ 116 | # [ // one possible three round game outcome 117 | # 'rock', // round 1 118 | # 'paper', // round 2 119 | # 'scissors' // round 3 120 | # ], 121 | # [ // next possible three round game outcome 122 | # 'rock', // round 1 123 | # 'paper', // round 2 124 | # 'rock' // round 3 125 | # ], 126 | # etc... 127 | # ] 128 | # 129 | # Extra credit: Make your function return answers for any number of rounds. 130 | # 131 | # Example: 132 | # rockPaperScissors(5); // => [['rock', 'rock', 'rock', 'rock', 'rock'], etc...] 133 | # 134 | 135 | def rock_paper_scissors(num) 136 | # base case 137 | return [] if num <= 0 138 | return [['rock'], ['paper'], ['scissors']] if num == 1 139 | 140 | # recursive case 141 | rock_paper_scissors(num - 1).reduce([]) do |acc, arr| 142 | acc + (['rock', 'paper', 'scissors'].map { |hand| arr + [hand] }) 143 | end 144 | end 145 | 146 | 147 | # 148 | # Given an array of values, produce all permutations of those values. 149 | # 150 | 151 | def permutations(array) 152 | len = array.length 153 | 154 | # base case 155 | return [] if len == 0 156 | return [array] if len == 1 157 | 158 | # recursive case 159 | first = array.take 1 160 | 161 | permutations(array.drop(1)).reduce([]) do |acc, arr| 162 | for i in 0..arr.length # include the length as the final index 163 | acc.push(arr.take(i) + first + arr.drop(i)) 164 | end 165 | acc 166 | end 167 | end 168 | 169 | 170 | # 171 | # Given an array of values, produce an array of all the combinations of those values. 172 | # 173 | 174 | def combinations(array) 175 | len = array.length 176 | 177 | # base case 178 | return [] if len == 0 179 | return [array] if len == 1 180 | 181 | # recursive case 182 | first = array.take 1 183 | rest = combinations array.drop(1) 184 | 185 | (rest.reduce([]) do |acc, arr| 186 | acc << (first + arr) 187 | acc << arr 188 | end) << first # reduce returns an array which I'm pushing first onto, and returning the entire expression 189 | end 190 | 191 | 192 | # 193 | # Given a sorted array, perform binary search 194 | # 195 | 196 | def binary_search(sorted_array, value) 197 | _binary_search(0, sorted_array.length, sorted_array, value) 198 | end 199 | 200 | def _binary_search(start, last, array, value) 201 | mid = (start + last) / 2 202 | 203 | return (value == array[mid] ? mid : nil) if mid == start || mid == last 204 | return mid if value == array[mid] 205 | return _binary_search(start, mid, array, value) if value < array[mid] 206 | _binary_search(mid, last, array, value) 207 | end 208 | 209 | 210 | # 211 | # Make an array method that can return whether or not a context array is a 212 | # subset of an input array. To simplify the problem, you can assume that both 213 | # arrays will contain only strings. 214 | # 215 | # See http://en.wikipedia.org/wiki/Subset for more on the definition of a 216 | # subset. 217 | # 218 | # 219 | # Extra credit: Make the method work for arrays that contain any value, 220 | # including non-strings. 221 | # 222 | 223 | def is_subset_of(base, input) 224 | require 'set' 225 | Set.new(input).subset? Set.new(base) 226 | end 227 | 228 | 229 | # 230 | # In England the currency is made up of pound, £, and pence, p, and there are eight coins in general circulation: 231 | # 232 | # 1p piece 233 | # 2p piece 234 | # 5p piece 235 | # 10p piece 236 | # 20p piece 237 | # 50p piece 238 | # 1 euro (100p) 239 | # 2 euro (200p) 240 | # 241 | # It is possible to make £2 in the following way: 242 | # 243 | # 1 * £1 + 1 * 50p + 2 * 20p + 1 * 5p + 1 * 2p + 3 * 1p 244 | # How many different ways can £2 be made using any number of coins? 245 | # 246 | # Example usage of `makeChange`: 247 | # 248 | # There's only one way to make 1p. that's with a single 1p piece 249 | # makeChange(1) === 1 250 | # 251 | # There's only two ways to make 2p. that's with two, 1p pieces or with a single 2p piece 252 | # makeChange(2) === 2 253 | # 254 | 255 | def make_change(amt) 256 | _make_change(amt, available_coins(amt)) 257 | end 258 | 259 | def available_coins(amt) 260 | [200, 100, 50, 20, 10, 5, 2, 1].find_all { |coin| amt >= coin } 261 | end 262 | 263 | def _make_change(amt, coin_array) 264 | # base cases 265 | return 0 if amt < 0 266 | return 1 if amt == 0 267 | 268 | # recursive case 269 | coin_array.reduce(0) do |acc, cur| 270 | acc + _make_change(amt - cur, available_coins(cur)) 271 | end 272 | end 273 | 274 | 275 | # 276 | # Write a function that takes as its input a string and returns an array of 277 | # arrays as shown below sorted in descending order by frequency and then by 278 | # ascending order by character. 279 | # 280 | # 281 | # :: Example :: 282 | # 283 | # character_frequency('mississippi') === 284 | # [ 285 | # ['i', 4], 286 | # ['s', 4], 287 | # ['p', 2], 288 | # ['m', 1] 289 | # ] 290 | # 291 | # :: Gotcha :: 292 | # 293 | # character_frequency('miaaiaaippi') === 294 | # [ 295 | # ['a', 4], 296 | # ['i', 4], 297 | # ['p', 2], 298 | # ['m', 1] 299 | # ] 300 | # 301 | # 302 | # 303 | 304 | def character_frequency(string) 305 | unsorted = convert_to_data_structure( create_string_hash(string) ) 306 | 307 | unsorted.sort do |arr1, arr2| 308 | result = 0 309 | if arr1[1] > arr2[1] 310 | result = -1 311 | elsif arr1[1] < arr2[1] 312 | result = 1 313 | elsif arr1[0].ord < arr2[0].ord 314 | result = -1 315 | else 316 | result = 1 317 | end 318 | result 319 | end 320 | end 321 | 322 | def create_string_hash(string) 323 | hash = {} 324 | string.each_char do |char| 325 | hash[char] ||= 0 326 | hash[char] += 1 327 | end 328 | hash 329 | end 330 | 331 | def convert_to_data_structure(hash) 332 | hash.reduce([]) do |acc, arr| 333 | acc << arr 334 | end 335 | end 336 | 337 | # 338 | # Anagram Detection 339 | # 340 | # Write a function that accepts two parameters, a parent and a child string. 341 | # Determine how many times the child string - or an anagram of the of the child 342 | # string - appears in the parent string. There is a solution which can be done 343 | # in near instant time. 344 | # 345 | # f('AdnBndAndBdaBn', 'dAn') // 4 ("Adn", "ndA", "dAn", "And") 346 | # f('AbrAcadAbRa', 'cAda') // 2 347 | # 348 | 349 | def num_anagrams(base, child) 350 | base_len = base.length 351 | child_len = child.length 352 | 353 | # base case 354 | return 0 if base_len < child_len 355 | 356 | # recursive case: child string can be as large as base string 357 | total = 0 358 | anagrams = create_anagrams child 359 | 360 | for i in 0..(base_len - child_len) 361 | str = base[i, child_len] 362 | total += 1 if anagrams.include? str 363 | end 364 | total 365 | end 366 | 367 | def create_anagrams(string) 368 | len = string.length 369 | 370 | # base cases 371 | return [] if len == 0 372 | return [string] if len == 1 373 | 374 | # recursive case 375 | first = string[0] 376 | rest = create_anagrams string[1...len] 377 | result = [] 378 | 379 | for element in rest # string 380 | el_len = element.length 381 | for i in 0..el_len 382 | result << (element[0...i] + first + element[i...el_len]) 383 | end 384 | end 385 | result 386 | end 387 | 388 | 389 | # 390 | # Binary Search Tree Check 391 | # 392 | # Given a binary tree, check whether it’s a binary search tree or not. 393 | # 394 | 395 | def is_binary_search_tree?(node) 396 | FIXNUM_MAX = (2**(0.size * 8 -2) -1) 397 | FIXNUM_MIN = -(2**(0.size * 8 -2)) 398 | 399 | _is_binary_search_tree(FIXNUM_MIN, FIXNUM_MAX, node) 400 | end 401 | 402 | def _is_binary_search_tree?(min, max, node) 403 | return true if node == nil 404 | return false if node.value < min || node.value > max 405 | return _is_binary_search_tree(min, node.value, node.left) && 406 | _is_binary_search_tree(node.value, max, node.right) 407 | end 408 | 409 | 410 | # 411 | # Array Pair Sum 412 | # 413 | # Given an integer array, output all pairs that sum up to a specific value k. 414 | # Consider the fact that the same number can add up to `k` with its duplicates 415 | # in the array. For example the array is [1, 1, 2, 3, 4] and the desired sum 416 | # is 4. Should we output the pair (1, 3) twice or just once? Also do we output 417 | # the reverse of a pair, meaning both (3, 1) and (1, 3)? Let’s keep the output 418 | # as short as possible and print each pair only once. So, we will output only 419 | # one copy of (1, 3). Also note that we shouldn’t output (2, 2) because it’s 420 | # not a pair of two distinct elements. 421 | # 422 | # Example 423 | # f(10, [3, 4, 5, 6, 7]) // [ [6, 4], [7, 3] ] 424 | # f(8, [3, 4, 5, 4, 4]) // [ [3, 5], [4, 4], [4, 4], [4, 4] ] 425 | # 426 | # Source 427 | # http://www.ardendertat.com/2011/09/17/programming-interview-questions-1-array-pair-sum/ 428 | # 429 | 430 | def array_pair_sum(num, array) 431 | len = array.length 432 | result = [] 433 | 434 | for start_at in 0..(len - 2) 435 | for end_at in (start_at + 1)..(len - 1) 436 | if array[start_at] + array[end_at] == num 437 | result << [ array[start_at], array[end_at] ] 438 | end 439 | end 440 | end 441 | 442 | result 443 | end 444 | 445 | 446 | # 447 | # Find Even Occurring Element 448 | # 449 | # Given an integer array, one element occurs even number of times and all 450 | # others have odd occurrences. Find the element with even occurrences. 451 | # 452 | 453 | def even_occurences(integer_array) 454 | hash = create_integer_hash integer_array 455 | 456 | result = hash.find_all do |key, value| 457 | value % 2 == 0 458 | end 459 | 460 | if result.length == 0 461 | raise 'All integers occur an odd number of times' 462 | elsif result.length == 1 463 | return result[0][0] 464 | else 465 | raise 'There are multiple even occurences' 466 | end 467 | end 468 | 469 | def create_integer_hash(integer_array) 470 | hash = {} 471 | integer_array.each do |num| 472 | hash[num] ||= 0 473 | hash[num] += 1 474 | end 475 | hash 476 | end 477 | 478 | # 479 | # Flatten Array 480 | # 481 | # Write a function that accepts a multi dimensional array and returns a 482 | # flattened version. 483 | # 484 | # my_flatten([1, 2, [3, [4], 5, 6], 7]) // [1, 2, 3, 4, 5, 6, 7] 485 | # 486 | 487 | def my_flatten(array) 488 | len = array.length 489 | 490 | # base case 491 | return array if len == 0 492 | 493 | # recursive case 494 | first = array[0] 495 | rest = array[1...len] 496 | 497 | # ternary operator 498 | (first.class == Array ? my_flatten(first) : [ first ]) + my_flatten(rest) 499 | end 500 | 501 | 502 | # 503 | # Integer Difference 504 | # 505 | # Write a function that accepts an array of random integers and an integer *n*. 506 | # Determine the number of times where two integers in the array have the 507 | # difference of *n*. 508 | # 509 | # f(4, [1, 1, 5, 6, 9, 16, 27]) // 3 (Due to 2x [1, 5], and [5, 9]) 510 | # f(2, [1, 1, 3, 3]) // 4 (Due to 4x [1, 3]) 511 | # 512 | 513 | def integer_difference(num, array) 514 | len = array.length 515 | total = 0 516 | 517 | for start_at in 0..(len - 2) 518 | for end_at in (start_at + 1)..(len - 1) 519 | total += 1 if (array[start_at] - array[end_at]).abs == num 520 | end 521 | end 522 | 523 | total 524 | end 525 | 526 | # 527 | # Largest Palindrome 528 | # 529 | # Write a function that finds the largest palindrome in a string. All 530 | # characters can be valid for the palindrome, including whitespace. In the 531 | # string "I am a red racecar driver" - the largest palindrome would be 532 | # "d racecar d". 533 | # 534 | 535 | def largest_palindrome(string) 536 | len = string.length 537 | result = '' 538 | max = 0 539 | 540 | for start_at in 0..(len - 1) 541 | for end_at in 0..(len - 1) 542 | str = string[start_at..end_at] 543 | if is_palindrome(str) && str.length > max 544 | result = str 545 | max = str.length 546 | end 547 | end 548 | end 549 | 550 | result 551 | end 552 | 553 | def is_palindrome(string) 554 | string == string.reverse 555 | end 556 | 557 | 558 | # 559 | # Longest Words 560 | # 561 | # Write a function that returns the longest word(s) from a sentence. The 562 | # function should not return any duplicate words (case-insensitive). 563 | # 564 | # longest_words("You are just an old antidisestablishmentarian") 565 | # => ["antidisestablishmentarian"] 566 | # longest_words("I gave a present to my parents") => ["present", "parents"] 567 | # longest_words("Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo 568 | # buffalo") => ["buffalo"] or ["Buffalo"] 569 | # 570 | 571 | def longest_words(string) 572 | require 'set' 573 | 574 | words = string.split(' ').map { |word| word.downcase } 575 | max_num_char = words.reduce(0) { |acc, word| [ acc, word.length ].max } 576 | unique_set = Set.new(words.find_all { |word| word.length == max_num_char }) 577 | 578 | unique_set.to_a 579 | end -------------------------------------------------------------------------------- /largestProductOfThree/largestProductOfThree.js: -------------------------------------------------------------------------------- 1 | /* Write a function that finds the largest possible product of any three numbers 2 | * from an array. 3 | * 4 | * Extra credit: Make your function handle negative numbers. 5 | */ 6 | 7 | var largestProductOfThree = function (array) { 8 | // Time Complexity: O(n^3) 9 | 10 | var result = []; 11 | var len = array.length; 12 | var first, second, third; 13 | var i, j, k; 14 | 15 | for (i = 0; i < len; i += 1) { 16 | first = array[i]; 17 | for (j = i + 1; j < len; j += 1) { 18 | second = array[j]; 19 | for (k = j + 1; k < len; k += 1) { 20 | third = array[k]; 21 | 22 | result.push( first * second * third ); 23 | } 24 | } 25 | } 26 | 27 | return Math.max.apply(null, result); 28 | }; 29 | 30 | var largestProductOfThree = function (array) { 31 | // Time Complexity: O(n * log(n)) 32 | 33 | if ( !Array.isArray(array) ) throw new Error('Must provide an Array of numbers'); 34 | if ( array.length < 3 ) throw new Error('Array must have at least 3 numbers'); 35 | 36 | /* 37 | * Array has at least 3 elements 38 | */ 39 | 40 | var len = array.length; 41 | var sortedArray, optionA, optionB; 42 | 43 | // sort the array => O(n * log(n)) 44 | sortedArray = array.sort(function (a, b) { return a - b; }); 45 | 46 | /* 47 | * The largest product of three numbers can be either: 48 | * 1) the two most negative numbers and the most positive number (option A) 49 | * 2) the three most positive numbers (option B) 50 | */ 51 | 52 | optionA = array[0] * array[1] * array[len - 1]; 53 | optionB = array[len - 3] * array[len - 2] * array[len - 1]; 54 | 55 | return Math.max( optionA , optionB ); 56 | }; -------------------------------------------------------------------------------- /linkedList/linkedList.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Implement a linked list using the pseudoclassical instantiation pattern. 3 | * 4 | * Your linked list should have methods called "addToTail", "removeHead", and "contains." 5 | * 6 | */ 7 | 8 | // EXAMPLE USAGE: 9 | // var list = new LinkedList(); 10 | // list.addToTail(4); 11 | // list.contains(4); //yields 'true'; 12 | // list.removeHead(); 13 | // list.tail; //yields 'null'; 14 | 15 | var LinkedList = function () { 16 | this.head = null; 17 | this.tail = null; 18 | }; 19 | 20 | //write methods here! 21 | 22 | LinkedList.prototype.addToTail = function (value) { 23 | var newNode = this.makeNode(value); 24 | 25 | if (this.isEmpty()) { 26 | this.head = newNode; 27 | this.tail = newNode; 28 | } else { 29 | this.tail.next = newNode; 30 | this.tail = newNode; 31 | } 32 | }; 33 | 34 | LinkedList.prototype.removeHead = function () { 35 | var result; 36 | if (!this.isEmpty()) { 37 | result = this.head.value; 38 | 39 | if (this.head === this.tail) { 40 | this.head = null; 41 | this.tail = null; 42 | } else { 43 | this.head = this.head.next; 44 | } 45 | 46 | return result; 47 | } 48 | }; 49 | 50 | LinkedList.prototype.contains = function (value, node) { 51 | if (this.isEmpty()) { 52 | return false; 53 | } 54 | 55 | // initialize node 56 | if (node === void 0) { 57 | node = this.head; 58 | } 59 | 60 | if (node === null) { 61 | return false; 62 | } else if (node.value === value) { 63 | return true; 64 | } else { 65 | return this.contains(value, node.next); 66 | } 67 | }; 68 | 69 | LinkedList.prototype.isEmpty = function () { 70 | return this.head === null && this.tail === null; 71 | }; 72 | 73 | LinkedList.prototype.makeNode = function (value) { 74 | return { 75 | value : value, 76 | next : null 77 | }; 78 | }; -------------------------------------------------------------------------------- /linkedListCycles/linkedListCycles.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Assignment: Write a function that returns true if a linked list contains a cycle, or false if it terminates somewhere 3 | * 4 | * Explanation: 5 | * 6 | * Generally, we assume that a linked list will terminate in a null next pointer, as follows: 7 | * 8 | * A -> B -> C -> D -> E -> null 9 | * 10 | * A 'cycle' in a linked list is when traversing the list would result in visiting the same nodes over and over 11 | * This is caused by pointing a node in the list to another node that already appeared earlier in the list. Example: 12 | * 13 | * A -> B -> C 14 | * ^ | 15 | * | v 16 | * E <- D 17 | * 18 | * Example code: 19 | * 20 | * var nodeA = Node('A'); 21 | * var nodeB = nodeA.next = Node('B'); 22 | * var nodeC = nodeB.next = Node('C'); 23 | * var nodeD = nodeC.next = Node('D'); 24 | * var nodeE = nodeD.next = Node('E'); 25 | * hasCycle(nodeA); // => false 26 | * nodeE.next = nodeB; 27 | * hasCycle(nodeA); // => true 28 | * 29 | * Constraint 1: Do this in linear time 30 | * Constraint 2: Do this in constant space 31 | * Constraint 3: Do not mutate the original nodes in any way 32 | */ 33 | 34 | var Node = function (value) { 35 | return { 36 | value : value, 37 | next : null 38 | }; 39 | }; 40 | 41 | var hasCycle = function (startNode) { 42 | // create two 'runners' who start at the same startNode 43 | var one = startNode; 44 | var two = startNode; 45 | 46 | while ( true ) { 47 | // check if the next one or two nodes are null 48 | if ( two.next === null || two.next.next === null ) return false; 49 | 50 | // one will go 'slower' than two 51 | one = one.next; 52 | two = two.next.next; 53 | 54 | // if there is a cycle, there eventually both of these runners will cross 55 | if ( one === two ) return true; 56 | } 57 | }; 58 | -------------------------------------------------------------------------------- /longestPalindrome/longestPalindrome.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implement a function that finds the longest palindrome in a given string. 3 | * For example, in the string "My dad is a racecar athlete", the longest 4 | * palindrome is "a racecar a". Count whitespaces as valid characters. Other 5 | * palindromes in the above string include "dad", "ete", " dad " (including 6 | * whitespace on each side of dad). 7 | */ 8 | 9 | var longestPalindrome = function (string) { 10 | var result = ''; 11 | var len = string.length; 12 | var i, j, word; 13 | 14 | for (i = 0; i < len; i += 1) { 15 | for (j = len; j > i; j -= 1) { 16 | word = string.slice(i, j); 17 | 18 | if ( isPalindrome( word ) && word.length > result.length) { 19 | result = word; 20 | } 21 | } 22 | } 23 | 24 | return result; 25 | }; 26 | 27 | var isPalindrome = function (string) { 28 | var len = string.length; 29 | 30 | if ( len < 2 ) return true; 31 | if ( string[0] !== string[len - 1] ) return false; 32 | return isPalindrome( string.slice(1, len - 1) ); 33 | }; -------------------------------------------------------------------------------- /longestRun/longestRun.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Write a function that, given a string, Finds the longest run of characters 3 | * and returns an array containing the start and end indices of that run. If 4 | * there are two runs of equal length, return the first one. For example: 5 | * 6 | * longestRun("abbbcc") // [1, 3] 7 | * longestRun("aabbc") // [0, 1] 8 | * longestRun("abcd") // [0, 0] 9 | * 10 | * Try your function with long, random strings to make sure it handles large 11 | * inputs well. 12 | */ 13 | 14 | var longestRun = function (string) { 15 | var strLen = string.length; 16 | if (strLen === 0) return []; 17 | if (strLen === 1) return [0, 0]; 18 | 19 | // strings of length 2 or greater 20 | var currentStart = 0; 21 | var currentLength = 1; 22 | var maxStart = 0; 23 | var maxLength = 1; 24 | var i; 25 | 26 | for (i = 1; i < strLen; i += 1) { 27 | // check if this character is the same as previous character 28 | if ( string[i] === string[i - 1] ) { 29 | currentLength += 1; 30 | } else { 31 | if (currentLength > maxLength) { 32 | maxStart = currentStart; 33 | maxLength = currentLength; 34 | } 35 | currentStart = i; 36 | currentLength = 1; 37 | } 38 | } 39 | 40 | return [ maxStart, maxStart + maxLength - 1 ]; 41 | }; 42 | 43 | // If you need a random string generator, use this! 44 | // (you wont need this function for your solution but it may help with testing) 45 | var randomString = function (len) { 46 | var text = ""; 47 | var possible = "abcdefghijklmnopqrstuvwxyz"; 48 | 49 | for(var i = 0; i < len; i++) { 50 | text += possible.charAt(Math.floor(Math.random() * possible.length)); 51 | } 52 | 53 | return text; 54 | }; 55 | -------------------------------------------------------------------------------- /nonrepeatedCharacter/nonrepeatedCharacter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Given an arbitrary input string, return the first nonrepeated character in 3 | * the string. For example: 4 | * 5 | * firstNonRepeatedCharacter('ABA'); // => 'B' 6 | * firstNonRepeatedCharacter('AACBDB'); // => 'C' 7 | */ 8 | 9 | var firstNonRepeatedCharacter = function (string) { 10 | // solution will have to be at least O(n) because you have to go through all characters 11 | // in string before you know whether any character is repeated 12 | if ( typeof string !== 'string' ) throw new Error('Must provide a string'); 13 | if ( string.length <= 0 ) throw new Error('String must be at least a character long'); 14 | 15 | var hash = {}; 16 | var len = string.length; 17 | var i; 18 | 19 | 20 | 21 | for (i = 0; i < len; i += 1) { 22 | if ( hash[ string[i] ] === void 0 ) { 23 | hash[ string[i] ] = true; 24 | } else if ( hash[ string[i] ] ) { 25 | hash[ string[i] ] = false; 26 | } 27 | } 28 | 29 | i = 0; 30 | while ( !hash[ string[i] ] ) { 31 | i += 1; 32 | } 33 | 34 | return string[i]; 35 | }; 36 | -------------------------------------------------------------------------------- /nthFibonacci/nthFibonacci.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A Fibonacci sequence is a list of numbers that begins with 0 and 1, and each 3 | * subsequent number is the sum of the previous two. 4 | * 5 | * For example, the first five Fibonacci numbers are: 6 | * 7 | * 0 1 1 2 3 8 | * 9 | * If n were 4, your function should return 3; for 5, it should return 5. 10 | * 11 | * Write a function that accepts a number, n, and returns the nth Fibonacci 12 | * number. Use a recursive solution to this problem; if you finish with time 13 | * left over, implement an iterative solution. 14 | * 15 | * example usage: 16 | * nthFibonacci(2); // => 1 17 | * nthFibonacci(3); // => 2 18 | * nthFibonacci(4); // => 3 19 | * etc... 20 | * 21 | */ 22 | 23 | // Recursive with memoization 24 | var nthFibonacci = (function () { 25 | var memo = {}; 26 | 27 | return function (n) { 28 | var nMinusOne, nMinusTwo, result; 29 | 30 | if ( n === 0 || n === 1 ) { 31 | if ( !memo[n] ) { memo[n] = n; } 32 | return memo[n]; 33 | } 34 | 35 | nMinusOne = memo[n - 1] || nthFibonacci(n - 1); 36 | nMinusTwo = memo[n - 2] || nthFibonacci(n - 2); 37 | result = nMinusOne + nMinusTwo; 38 | memo[n] = result; 39 | 40 | return memo[n]; 41 | }; 42 | })(); 43 | 44 | // Iterative 45 | var nthFibonacci = function (n) { 46 | var previousOne, previousTwo, result; 47 | 48 | if (n === 1 || n === 0) { 49 | return n; 50 | } 51 | 52 | previousOne = 1; 53 | previousTwo = 0; 54 | 55 | for (var i = 2; i <= n; i += 1) { 56 | result = previousOne + previousTwo; 57 | previousTwo = previousOne; 58 | previousOne = result; 59 | } 60 | 61 | return result; 62 | }; -------------------------------------------------------------------------------- /numberToEnglish/numberToEnglish.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Extend the Number prototype with a new method called `toEnglish`. 3 | * It should return the number as a string using English words. 4 | * Examples: 5 | * (7).toEnglish(); // > "seven" 6 | * (575).toEnglish(); // > "five hundred seventy-five" 7 | * (78193512).toEnglish(); // > "seventy-eight million one hundred ninety-three thousand five hundred twelve" 8 | * 9 | * Extra credit: Make your function support decimals. 10 | * Example: 11 | * (150043.273).toEnglish() // > "one hundred fifty thousand forty-three and two hundred seventy three thousandths" 12 | * 13 | */ 14 | 15 | var numbersToWords = { 16 | 0: 'zero', 17 | 1: 'one', 18 | 2: 'two', 19 | 3: 'three', 20 | 4: 'four', 21 | 5: 'five', 22 | 6: 'six', 23 | 7: 'seven', 24 | 8: 'eight', 25 | 9: 'nine', 26 | 10: 'ten', 27 | 11: 'eleven', 28 | 12: 'twelve', 29 | 13: 'thirteen', 30 | 14: 'fourteen', 31 | 15: 'fifteen', 32 | 16: 'sixteen', 33 | 17: 'seventeen', 34 | 18: 'eighteen', 35 | 19: 'nineteen', 36 | 20: 'twenty', 37 | 30: 'thirty', 38 | 40: 'forty', 39 | 50: 'fifty', 40 | 60: 'sixty', 41 | 70: 'seventy', 42 | 80: 'eighty', 43 | 90: 'ninety', 44 | }; 45 | var numbersToPlace = { 46 | 10: 'ten', 47 | 100: 'hundred', 48 | 1000: 'thousand', 49 | 1000000: 'million', 50 | 1000000000: 'billion', 51 | 1000000000000: 'trillion', 52 | 1000000000000000: 'quadrillion', 53 | 1000000000000000000: 'quintillion', 54 | }; 55 | 56 | Number.prototype.toEnglish = function () { 57 | // return my value as english words 58 | }; 59 | -------------------------------------------------------------------------------- /powerSet/powerSet.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Return an array with the power set of a given string. 3 | * 4 | * Example: 5 | * 6 | * powerSet("abc") 7 | * -> [ '' , 'a', 'b', 'c', 'ab', 'ac', 'bc', 'abc' ] 8 | * 9 | * Note: result does need to be sorted or in any particular order, it only needs to contain 10 | * the correct set of values. 11 | */ 12 | 13 | var powerSet = function (str) { 14 | if (str.length === 0) return ['']; 15 | if (str.length === 1) return [ str ]; 16 | 17 | var result = []; 18 | var first = str[0]; 19 | var rest = str.slice(1); 20 | var recur = powerSet( rest ); 21 | 22 | recur.forEach( function (s) { 23 | result.push( s ); 24 | result.push( first + s ); 25 | }); 26 | 27 | result.push( first ); 28 | 29 | return result; 30 | }; -------------------------------------------------------------------------------- /primeTester/primeTester.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A prime number is a whole number that has no other divisors other than 3 | * itself and 1. Write a function that accepts a number and returns true if it's 4 | * a prime number, false if it's not. 5 | */ 6 | 7 | var primeTester = (function () { 8 | var cache = {}; 9 | 10 | return function (n) { 11 | if ( typeof n !== 'number' ) return false; 12 | 13 | // if number is in cache, return results from cache 14 | if ( cache[n] ) return cache[n]; 15 | 16 | // n is less than 1 or n is not an integer 17 | if ( n <= 1 || n % 1 !== 0 ) { 18 | cache[n] = false; 19 | } else { 20 | for (var i = 2; i < n; i += 1) { 21 | if (n % i === 0) { 22 | cache[n] = false; 23 | return cache[n]; 24 | } 25 | } 26 | cache[n] = true; 27 | } 28 | 29 | return cache[n]; 30 | }; 31 | })(); 32 | 33 | /* Extra credit: Write a function that generates a list of all prime numbers 34 | * in a user-specified range (inclusive). If you're not quite sure where to start, 35 | * check out the Sieve of Eratosthenes on Wikipedia. (And if you're feeling 36 | * saucy, check out the Sieve of Atkin.) 37 | */ 38 | 39 | var primeSieve = function (start, end) { 40 | // Return a list of all prime numbers >= start and <= end 41 | var result = []; 42 | var i; 43 | 44 | for (i = start; i <= end; i += 1) { 45 | if ( primeTester(i) ) { 46 | result.push( i ); 47 | } 48 | } 49 | 50 | return result; 51 | }; 52 | 53 | // Sieve of Eratosthenes 54 | var generateListOfPrimesLessThanOrEqualTo = function (num) { 55 | if ( num < 2 ) return []; 56 | 57 | var flags = init(num); 58 | var prime = 2; 59 | 60 | while (prime <= num) { 61 | crossOff( flags, prime ); 62 | prime = getNextPrime( flags, prime ); 63 | } 64 | 65 | return filter(flags, function (bool) { return bool; }); 66 | }; 67 | 68 | var init = function (num) { 69 | var obj = {}; 70 | for (var i = 0; i <= num; i += 1) { 71 | obj[i] = true; 72 | } 73 | 74 | // 0 and 1 are not primes by definition 75 | obj[0] = false; 76 | obj[1] = false; 77 | 78 | return obj; 79 | }; 80 | 81 | var crossOff = function (flags, prime) { 82 | var len = Object.keys( flags ).length; 83 | 84 | for (var i = prime * prime; i < len; i += prime) { 85 | flags[i] = false; 86 | } 87 | }; 88 | 89 | var getNextPrime = function (flags, prime) { 90 | var next = prime + 1; 91 | var len = Object.keys( flags ).length; 92 | 93 | while (next < len && !flags[next]) { 94 | next += 1; 95 | } 96 | return next; 97 | }; 98 | 99 | var filter = function (obj, fn) { 100 | var result = []; 101 | for (var prop in obj) { 102 | if ( fn(obj[prop]) ) { 103 | result.push( parseInt(prop, 10) ); 104 | } 105 | } 106 | return result; 107 | }; -------------------------------------------------------------------------------- /queueStack/queueStack.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Write a stack using your preferred instantiation pattern. Once you're done, 3 | * implement a queue using two stacks. 4 | */ 5 | 6 | /** 7 | * Stack Class 8 | */ 9 | 10 | var Stack = function () { 11 | var storage = {}; 12 | var size = 0; 13 | 14 | // add an item to the top of the stack 15 | this.push = function (value) { 16 | storage[ size ] = value; 17 | size += 1; 18 | }; 19 | 20 | // remove an item from the top of the stack 21 | this.pop = function () { 22 | var popped; 23 | if ( this.size() > 0 ) { 24 | popped = storage[ size - 1 ]; 25 | delete storage[ size - 1 ]; 26 | size -= 1; 27 | return popped; 28 | } 29 | }; 30 | 31 | // return the number of items in the stack 32 | this.size = function () { 33 | return size; 34 | }; 35 | }; 36 | 37 | /** 38 | * Queue Class 39 | */ 40 | var Queue = function() { 41 | // Use two `stack` instances to implement your `queue` Class 42 | var inbox = new Stack(); 43 | var outbox = new Stack(); 44 | 45 | // called to add an item to the `queue` 46 | this.enqueue = function (value) { 47 | inbox.push( value ); 48 | }; 49 | 50 | // called to remove an item from the `queue` 51 | this.dequeue = function () { 52 | var temp, popped; 53 | 54 | while ( inbox.size() > 0 ) { 55 | temp = inbox.pop(); 56 | outbox.push( temp ); 57 | } 58 | 59 | popped = outbox.pop(); 60 | 61 | while ( outbox.size() > 0 ) { 62 | temp = outbox.pop(); 63 | inbox.push( temp ); 64 | } 65 | 66 | return popped; 67 | }; 68 | 69 | // should return the number of items in the queue 70 | this.size = function () { 71 | return inbox.size(); 72 | }; 73 | }; 74 | -------------------------------------------------------------------------------- /rangeClass/rangeClass.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Build a class to represent a range of numbers, modeled after Ruby's "range" class, that takes: 3 | * - a beginning index, 4 | * - an end index (optional) 5 | * - a 'step' (optional) 6 | * The step is the interval at which elements are included. 7 | * For instance, a step of 1 includes every element in the range, 8 | * while a step of 2 includes every other element. 9 | * 10 | * The range should have a constructor that accepts these arguments in that order. 11 | * 12 | * It should also support the following utility functions: 13 | * - size(): return the number of items represented by the range 14 | * - each(callback(index)): iterate over the array, passing each value to a callback function 15 | * - includes(index): return whether or not the range includes the passed value 16 | * 17 | * You should also be aware of the following caveats: 18 | * - You should allow a negative value for 'step' to count backwards. 19 | * If no step is provided and the start is more than the end, assume we're counting backwards. 20 | * - Should throw an exception if we are given no 'start' value. 21 | * 22 | * USAGE EXAMPLES: 23 | * var myRange = new Range(0,10); // a new range representing the numbers between 0 and 10 (inclusively) 24 | * 25 | * var evenNumbers = new Range(2,8,2); // A range with the even numbers 2, 4, 6, and 8. 26 | * evenNumbers.each(function(val){ 27 | * console.log(val+"!"); 28 | * }); 29 | * console.log("Who do we appreciate!?"); 30 | * 31 | * evenNumbers.size() should be 4 32 | * evenNumbers.includes(2) should be true, evenNumbers.include(3) should be false 33 | */ 34 | 35 | 36 | var Range = function(start, end, step) { 37 | // TODO: Your code here 38 | 39 | this.size = function(){ 40 | // TODO: Your code here 41 | } 42 | 43 | this.each = function(callback){ 44 | // TODO: Your code here 45 | } 46 | 47 | this.includes = function(val){ 48 | // TODO: Your code here 49 | } 50 | 51 | return this; 52 | } -------------------------------------------------------------------------------- /redo.js: -------------------------------------------------------------------------------- 1 | var permutations = function (array) { 2 | var len = array.length; 3 | if (len === 0) { return []; } 4 | if (len === 1) { return [ array ]; } 5 | 6 | var first = array.slice(0, 1); 7 | var rest = array.slice(1); 8 | 9 | return permutations( rest ).reduce(function (acc, cur) { 10 | var len = cur.length; 11 | 12 | for (var i = 0; i < len; i += 1) { 13 | acc.push( Array.prototype.concat.call( cur.slice(0, i), first, cur.slice(i) ) ); 14 | } 15 | acc.push( Array.prototype.concat.call( cur, first ) ); 16 | 17 | return acc; 18 | }, []); 19 | }; 20 | 21 | 22 | var combinations = function (array) { 23 | var len = array.length; 24 | var result = []; 25 | var first, rest; 26 | 27 | if (len === 0) { return []; } 28 | if (len === 1) { return [ array ]; } 29 | 30 | first = array[0]; 31 | rest = array.slice(1); 32 | 33 | combinations( rest ).forEach(function (arr) { 34 | result.push( arr.concat(first) ); 35 | result.push( arr ); 36 | }); 37 | result.push( [ first ] ); 38 | 39 | return result; 40 | }; 41 | 42 | 43 | var rockPaperScissors = function (num) { 44 | if (num <= 0) { return []; } 45 | if (num === 1) { return [ ['rock'], ['paper'], ['scissors'] ]; } 46 | 47 | var result = []; 48 | 49 | rockPaperScissors(num - 1).forEach(function (arr) { 50 | ['rock', 'paper', 'scissors'].forEach(function (hand) { 51 | result.push( Array.prototype.concat( arr, hand ) ); 52 | }); 53 | }); 54 | 55 | return result; 56 | }; 57 | 58 | 59 | var balancedParens = function (string) { 60 | var stack = []; 61 | var character, popped; 62 | 63 | var isOpening = function (character) { 64 | return character === '(' || 65 | character === '[' || 66 | character === '{'; 67 | }; 68 | 69 | var map = { 70 | ')' : '(', 71 | ']' : '[', 72 | '}' : '{' 73 | }; 74 | 75 | for (var i = 0; i < string.length; i += 1) { 76 | character = string[i]; 77 | 78 | if ( isOpening(character) ) { 79 | stack.push( character ); 80 | } else if ( map[ character ] ) { 81 | popped = stack.pop(); 82 | if ( map[character] !== popped ) { return false; } 83 | } 84 | } 85 | 86 | return stack.length === 0; 87 | }; 88 | 89 | 90 | var binarySearch = function (arr, num) { 91 | var inner = function (start, end) { 92 | var mid = Math.floor( (start + end) / 2 ); 93 | 94 | if (start >= end) { return null; } 95 | if (num === arr[mid]) { return mid; } 96 | if (num < arr[mid]) { return inner(start, mid); } 97 | return inner(mid + 1, end); 98 | }; 99 | 100 | return inner(0, arr.length); 101 | }; 102 | 103 | 104 | var characterFrequency = function (string) { 105 | var createHash = function (string) { 106 | var hash = {}; 107 | for (var i = 0; i < string.length; i += 1) { 108 | hash[ string[i] ] = hash[ string[i] ] || 0; 109 | hash[ string[i] ] += 1; 110 | } 111 | return hash; 112 | }; 113 | 114 | var createDataStructure = function (hash) { 115 | var result = []; 116 | for (var prop in hash) { 117 | result.push([ prop, hash[prop] ]); 118 | } 119 | return result; 120 | }; 121 | 122 | var dsHash = createDataStructure( createHash(string) ); 123 | 124 | dsHash.sort(function (a, b) { 125 | // a and b are arrays 126 | if (a[1] > b[1]) { 127 | return -1; 128 | } else if (a[1] < b[1]) { 129 | return 1; 130 | } else { 131 | return a[0] >= b[0] ? 1 : -1; 132 | } 133 | }); 134 | 135 | return dsHash; 136 | }; 137 | 138 | 139 | var makeChange = function (num) { 140 | var inner = function (num, coins) { 141 | if (num < 0) { return 0; } 142 | if (num === 0) { return 1; } 143 | 144 | var total = 0; 145 | coins.forEach(function (amt) { 146 | total += inner(num - amt, availableCoins(amt)); 147 | }); 148 | 149 | return total; 150 | }; 151 | 152 | return inner(num, availableCoins(num)); 153 | }; 154 | 155 | var availableCoins = function (num) { 156 | return [200, 100, 50, 20, 10, 5, 2, 1].filter(function (n) { 157 | return num >= n; 158 | }); 159 | }; 160 | 161 | 162 | var convertToHash = function (string) { 163 | var hash = {}; 164 | for (var i = 0; i < string.length; i += 1) { 165 | hash[string[i]] = true; 166 | } 167 | return hash; 168 | }; 169 | 170 | var combineHash = function (hash1, hash2) { 171 | var result = {}; 172 | for (var prop in hash1) { 173 | if (hash2[prop]) { 174 | result[prop] = true; 175 | } 176 | } 177 | return result; 178 | }; 179 | 180 | var commonCharacters = function () { 181 | var args = Array.prototype.slice.call(arguments); 182 | var first = args[0]; 183 | var result = args 184 | .map(function (string) { 185 | return convertToHash(string); 186 | }) 187 | .reduce(function (acc, cur) { 188 | return combineHash(acc, cur); 189 | }); 190 | 191 | return first.split('') 192 | .filter(function (character) { 193 | var temp = result[character]; 194 | delete result[character]; 195 | return temp; 196 | }) 197 | .join(''); 198 | }; 199 | 200 | 201 | var mixEvents = function (obj) { 202 | var eventHash = {}; 203 | 204 | obj.on = function (e, callback) { 205 | // check if event already exists in eventHash 206 | eventHash[ e ] = eventHash[ e ] || []; 207 | eventHash[ e ].push( callback ); 208 | }; 209 | 210 | obj.trigger = function (e) { 211 | var args = Array.prototype.slice.call(arguments, 1); 212 | var allCallbacks = eventHash[ e ]; 213 | allCallbacks.forEach(function (fn) { 214 | fn.apply(this, args); 215 | }); 216 | }; 217 | 218 | return obj; 219 | }; 220 | 221 | 222 | Array.prototype.isSubsetOf = function (base) { 223 | var thisLen = this.length; 224 | var baseLen = base.length; 225 | var isFound, i, j; 226 | 227 | if (thisLen > baseLen) return false; 228 | 229 | // 'this' array contains at most base array's number of elements 230 | for (i = 0; i < thisLen; i += 1) { 231 | isFound = false; 232 | for (j = 0; j < baseLen; j += 1) { 233 | if (this[i] === base[j]) { 234 | isFound = true; 235 | } 236 | } 237 | // check if isFound has flipped 238 | if (!isFound) return false; 239 | } 240 | 241 | return true; 242 | }; 243 | 244 | 245 | var quickSort = function (array) { 246 | // base case 247 | if (array.length < 2) return array; 248 | 249 | var pivot = array.splice(0, 1)[0]; 250 | var left = []; 251 | var right = []; 252 | var len = array.length; 253 | var i; 254 | 255 | for (i = 0; i < len; i += 1) { 256 | (array[i] <= pivot ? left : right).push( array[i] ); 257 | } 258 | 259 | return Array.prototype.concat.call( quickSort(left), pivot, quickSort(right) ); 260 | }; 261 | 262 | 263 | var mergeSort = function (array) { 264 | var len = array.length; 265 | if (len < 2) return array; 266 | 267 | var mid = Math.floor(len / 2); 268 | var left = mergeSort( array.slice(0, mid) ); 269 | var right = mergeSort( array.slice(mid) ); 270 | 271 | return merge(array, left, right); 272 | }; 273 | 274 | var merge = function (array, left, right) { 275 | var leftLen = left.length; 276 | var rightLen = right.length; 277 | var i = 0; 278 | var j = 0; 279 | var k = 0; 280 | 281 | while (j < leftLen && k < rightLen) { 282 | if (left[j] <= right[k]) { 283 | array[i] = left[j]; 284 | j += 1; 285 | } else { 286 | array[i] = right[k]; 287 | k += 1; 288 | } 289 | i += 1; 290 | } 291 | 292 | while (j < leftLen) { 293 | array[i] = left[j]; 294 | i += 1; 295 | j += 1; 296 | } 297 | 298 | while (k < rightLen) { 299 | array[i] = right[k]; 300 | i += 1; 301 | k += 1; 302 | } 303 | 304 | return array; 305 | }; -------------------------------------------------------------------------------- /reverseArray/reverseArray.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Given an arbitrary input array, write a function that reverses the contents 3 | * of the array (ie, without modifying the original array.) 4 | * Don't use the native Array.prototype.reverse() method. 5 | * 6 | * Extra Credit: Reverse in-place (don't use an extra array). 7 | * 8 | * 9 | * Here's a sample input to get you going: 10 | * 11 | * reverseArray([1, 8, 39, null, 2, 9, 'bob'])[0] // should equal => 'bob' 12 | */ 13 | 14 | var reverseArray = function (array) { 15 | var length = array.length; 16 | var start = 0; 17 | var end = length - 1; 18 | var temp; 19 | 20 | while (start < end) { 21 | temp = array[start]; 22 | array[start] = array[end]; 23 | array[end] = temp; 24 | 25 | start += 1; 26 | end -= 1; 27 | } 28 | 29 | return array; 30 | }; 31 | -------------------------------------------------------------------------------- /robotPaths/robotPaths.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * A robot located at the top left corner of a 5x5 grid is trying to reach the 4 | * bottom right corner. The robot can move either up, down, left, or right, 5 | * but cannot visit the same spot twice. How many possible unique paths are 6 | * there to the bottom right corner? 7 | * 8 | * make your solution work for a grid of any size. 9 | * 10 | */ 11 | 12 | // A Board class will be useful 13 | 14 | var makeBoard = function (n) { 15 | var board = []; 16 | 17 | for (var i = 0; i < n; i++) { 18 | board.push([]); 19 | for (var j = 0; j < n; j++) { 20 | board[i].push(false); 21 | } 22 | } 23 | 24 | board.togglePiece = function (i, j) { 25 | this[i][j] = !this[i][j]; 26 | }; 27 | 28 | board.hasBeenVisited = function (i, j) { 29 | return !!this[i][j]; 30 | }; 31 | 32 | board.withInBoard = function (i, j) { 33 | return (i >= 0 && i < n && j >= 0 && j < n); 34 | }; 35 | 36 | return board; 37 | }; 38 | 39 | var robotPaths = function (n) { 40 | var total = 0; 41 | var board = makeBoard(n); 42 | var inner = function (board, x, y) { 43 | // base case 44 | if (x === n - 1 && y === n - 1 && !board.hasBeenVisited(x, y)) { 45 | total += 1; 46 | return; 47 | } 48 | 49 | if (board.withInBoard(x, y) && !board.hasBeenVisited(x, y)) { 50 | board.togglePiece(x, y); 51 | 52 | // check left position 53 | inner(board, x - 1, y); 54 | // check right position 55 | inner(board, x + 1, y); 56 | // check top position 57 | inner(board, x, y - 1); 58 | // check bottom position 59 | inner(board, x, y + 1); 60 | 61 | // untoggle current position 62 | board.togglePiece(x, y); 63 | } 64 | }; 65 | 66 | inner(board, 0, 0); 67 | return total; 68 | }; -------------------------------------------------------------------------------- /rockPaperScissors/rockPaperScissors.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Write a function that generates every sequence of throws a single 3 | * player could throw over a three-round game of rock-paper-scissors. 4 | * 5 | * Example: 6 | * [ 7 | * [ // one possible three round game outcome 8 | * 'rock', // round 1 9 | * 'paper', // round 2 10 | * 'scissors' // round 3 11 | * ], 12 | * [ // next possible three round game outcome 13 | * 'rock', // round 1 14 | * 'paper', // round 2 15 | * 'rock' // round 3 16 | * ], 17 | * etc... 18 | * ] 19 | * 20 | * Extra credit: 21 | * - Make your function return answers for any number of rounds. 22 | * Example: 23 | * rockPaperScissors(5); // => [['rock', 'rock', 'rock', 'rock', 'rock'], etc...] 24 | * 25 | */ 26 | 27 | var rockPaperScissors = function (n) { 28 | var result = []; 29 | var choices = ['rock', 'paper', 'scissors']; 30 | var previous; 31 | 32 | // base cases 33 | if ( n <= 0 ) return result; 34 | if ( n === 1 ) return [ ['rock'], ['paper'], ['scissors'] ]; 35 | 36 | previous = rockPaperScissors(n - 1); 37 | 38 | // for each array in previous 39 | previous.forEach(function (array) { 40 | // for each choice in choices 41 | choices.forEach(function (choice) { 42 | // concatenate previous array with choice and push to result 43 | result.push( Array.prototype.concat( array, choice ) ); 44 | }); 45 | }); 46 | 47 | return result; 48 | }; 49 | -------------------------------------------------------------------------------- /rockPaperScissorsII/rockPaperScissors.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Write a function that generates every sequence of throws a single 3 | * player could throw over a three-round game of rock-paper-scissors. 4 | * 5 | * Example: 6 | * [ 7 | * [ // one possible three round game outcome 8 | * 'rock', // round 1 9 | * 'paper', // round 2 10 | * 'scissors' // round 3 11 | * ], 12 | * [ // next possible three round game outcome 13 | * 'rock', // round 1 14 | * 'paper', // round 2 15 | * 'rock' // round 3 16 | * ], 17 | * etc... 18 | * ] 19 | * 20 | * Extra credit: 21 | * - Make your function return answers for any number of rounds. 22 | * Example: 23 | * rockPaperScissors(5); // => [['rock', 'rock', 'rock', 'rock', 'rock'], etc...] 24 | * 25 | */ 26 | 27 | var rockPaperScissors = function (n) { 28 | var result = []; 29 | var choices = ['rock', 'paper', 'scissors']; 30 | var previous; 31 | 32 | if (n <= 0) return result; 33 | if (n === 1) return [ ['rock'], ['paper'], ['scissors'] ]; 34 | 35 | previous = rockPaperScissors( n - 1 ); 36 | previous.forEach(function (array) { 37 | choices.forEach(function (choice) { 38 | result.push( Array.prototype.concat( array, choice ) ); 39 | }); 40 | }); 41 | 42 | return result; 43 | }; 44 | -------------------------------------------------------------------------------- /romanNumeralTranslator/romanNumeralTranslator.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Given a roman numeral as input, write a function that converts the roman 4 | * numeral to a number and outputs it. 5 | * 6 | * Ex: 7 | * translateRomanNumeral("LX") // 60 8 | * 9 | * When a smaller numeral appears before a larger one, it becomes 10 | * a subtractive obertion. You can assume only one smaller numeral 11 | * may appear in front of larger one. 12 | * 13 | * Ex: 14 | * translateRomanNumeral("IV") // 4 15 | * 16 | */ 17 | 18 | var DIGIT_VALUES = { 19 | I: 1, 20 | V: 5, 21 | X: 10, 22 | L: 50, 23 | C: 100, 24 | D: 500, 25 | M: 1000 26 | }; 27 | 28 | var translateRomanNumeral = function (romanNumeral) { 29 | if (typeof romanNumeral !== 'string') { 30 | throw 'function "translateRomanNumeral" can only process strings'; 31 | } 32 | 33 | var len = romanNumeral.length; 34 | var result = 0; 35 | var i, current, next; 36 | 37 | // base case 38 | if (len <= 0) return 0; 39 | if (len === 1) return DIGIT_VALUES[ romanNumeral ]; 40 | 41 | for (i = 0; i < len - 1; i += 1) { 42 | current = DIGIT_VALUES[ romanNumeral[i] ]; 43 | next = DIGIT_VALUES[ romanNumeral[i + 1] ]; 44 | if ( current === void 0 || next === void 0 ) throw new Error('Invalid roman numeral characters'); 45 | 46 | result += (current >= next ? current : -current); 47 | } 48 | 49 | return result + DIGIT_VALUES[ romanNumeral[i] ]; 50 | }; -------------------------------------------------------------------------------- /rotateMatrix/rotateMatrix.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Write a function that rotates a NxN matrix 90 degrees. 3 | * 4 | * A matrix, also called a 2-D array, is simply an array of arrays of values. 5 | * 6 | * Example 1x1 matrix: 7 | * [ [1] ] 8 | * 9 | * Example 2x2 matrix: 10 | * [ [1,2], 11 | * [3,4] ] 12 | * 13 | * Important note: 14 | * In mathematics, and generally in CS, matrices are identified as m-by-n, where m is 15 | * the number of *rows* and n is the number of *columns*. So an [i][j] address in a matrix 16 | * will be i places down, and j places over. This usually matches the way arrays are 17 | * addressed in code, but keep in mind that it differs from use in geometry and computer 18 | * graphics, where coordinates of the form (x,y) are usually x units over, and y units down. 19 | * 20 | * Example rotation of a 4x4 matrix: 21 | * 22 | * var matrix = [ 23 | * [1,2,3,4], 24 | * [5,6,7,8], 25 | * [9,'A','B','C'], 26 | * ['D','E','F','G'] 27 | * ]; 28 | * matrix[0][0]; // 1 29 | * matrix[3][2]; // 'F' 30 | * 31 | * rotatedMatrix = rotateMatrix(matrix); // Rotate 90 degrees clockwise 32 | * // rotatedMatrix is: 33 | * [ ['D',9,5,1], 34 | * ['E','A',6,2], 35 | * ['F','B',7,3], 36 | * ['G','C',8,4] 37 | * ] 38 | * rotatedMatrix[0][0]; // 'D' 39 | * rotatedMatrix[3][2]; // 8 40 | * 41 | * Extra credit: 42 | * - Make your function operate on rectangular matrices (MxN rather than NxN). 43 | * - Make your function accept a parameter for the direction of rotation (1 = clockwise, -1 = counterclockwise) 44 | */ 45 | 46 | var rotateMatrix = function (matrix, direction) { 47 | direction = direction || 1; 48 | if ( typeof direction !== 'number' || (direction !== 1 && direction !== -1) ) { 49 | throw new Error('direction must be 1 for clockwise or -1 for counterclockwise'); 50 | } 51 | 52 | var rows = matrix.length; 53 | var cols = matrix[0].length; 54 | var newRows = cols; 55 | var newCols = rows; 56 | var result = []; 57 | var i, j, k; 58 | 59 | // give result matrix the correct number of rows 60 | for (k = 0; k < cols; k += 1) { 61 | result.push( [] ); 62 | } 63 | 64 | for (i = 0; i < newRows; i += 1) { 65 | for (j = 0; j < newCols; j += 1) { 66 | result[i][j] = direction === 1 ? 67 | matrix[newCols - j - 1][i] : 68 | matrix[j][newRows - i - 1]; 69 | } 70 | } 71 | 72 | return result; 73 | }; -------------------------------------------------------------------------------- /shuffleDeck/shuffleDeck.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Given an array containing a deck of cards, implement a function that shuffles 3 | * the deck. 4 | * 5 | * Example: 6 | * var deck = orderedDeck(); 7 | * // ["A♥","2♥","3♥",...,"J♦","Q♦","K♦"] 8 | * shuffleDeck(deck); 9 | * // ["2♠","J♣","A♦", ... ,"7♣","8♣","K♠"] 10 | * 11 | * Note: 12 | * A shuffled deck should be completely random. That means that a given card should 13 | * be as likely as any other to appear in a given deck index, completely independent 14 | * of the order of the input deck. Think carefully about how to be sure your algorithm 15 | * generates a properly shuffled deck-- it is easy to accidentally create a biased algorithm. 16 | * 17 | * Extra credit: 18 | * - Even a naive algorithm can easily run in linear time. However, does your 19 | * algorithm remain unbiased as N (the deck size) increases? How do you know? 20 | * - Once you have created a properly random, linear algorithm, what is its space complexity? 21 | * There is an algorithm that uses O(N) time and O(1) space (i.e., an in-place shuffle). 22 | * 23 | * A further note on randomness: 24 | * Technically, a computer-shuffled deck will usually be "pseudorandom", 25 | * not "truly" random. However, the difference between the two is too small to 26 | * be detectable by any known test. 27 | * See http://en.wikipedia.org/wiki/Pseudorandom_number_generator . 28 | * 29 | * A human shuffler is much more biased; it takes around seven normal "riffle" 30 | * shuffles before a real deck is actually randomized. 31 | * See https://www.dartmouth.edu/~chance/teaching_aids/books_articles/Mann.pdf . 32 | */ 33 | 34 | // Apparently, this is biased... 35 | // var shuffleDeck = function (deck) { 36 | // var len = deck.length; 37 | // var i; 38 | 39 | // for (i = 0; i < len; i += 1) { 40 | // swap(deck, i, Math.floor( Math.random() * len ) ); 41 | // } 42 | 43 | // return deck; 44 | // }; 45 | 46 | var shuffleDeck = function (deck) { 47 | var numUnshuffledCards = deck.length; 48 | var randomIdx; 49 | 50 | while ( numUnshuffledCards > 0 ) { 51 | randomIdx = Math.floor( Math.random() * numUnshuffledCards ); 52 | numUnshuffledCards -= 1; 53 | swap( deck, numUnshuffledCards, randomIdx ); 54 | } 55 | 56 | return deck; 57 | }; 58 | 59 | var swap = function (deck, i, j) { 60 | var temp = deck[i]; 61 | deck[i] = deck[j]; 62 | deck[j] = temp; 63 | }; 64 | 65 | // Ordered deck generator provided for your testing convenience 66 | // (You may alter this function, but an unaltered copy will be used for tests.) 67 | var orderedDeck = function () { 68 | var suits = [ '♥', '♣', '♠', '♦' ]; 69 | var values = [ 'A', 2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K' ]; 70 | var deck = []; 71 | 72 | suits.forEach(function(suit) { 73 | values.forEach(function(value) { 74 | deck.push(value + suit); 75 | }); 76 | }); 77 | 78 | return deck; 79 | }; 80 | -------------------------------------------------------------------------------- /sortableTable/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | sortableTable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |

Sortable Table

27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 |
Item NameNumber of PoundsPrice Per PoundExpiration Date
bananas251.992014-08-11
almonds610.502014-10-06
rice1501.502014-10-05
mangos832.002014-12-20
potatos251.352014-09-11
69 | 70 | 71 | -------------------------------------------------------------------------------- /sortableTable/lib/jquery-2.1.0.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery v2.1.0 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ 2 | !function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k="".trim,l={},m=a.document,n="2.1.0",o=function(a,b){return new o.fn.init(a,b)},p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};o.fn=o.prototype={jquery:n,constructor:o,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=o.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return o.each(this,a,b)},map:function(a){return this.pushStack(o.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},o.extend=o.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||o.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(o.isPlainObject(d)||(e=o.isArray(d)))?(e?(e=!1,f=c&&o.isArray(c)?c:[]):f=c&&o.isPlainObject(c)?c:{},g[b]=o.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},o.extend({expando:"jQuery"+(n+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===o.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return a-parseFloat(a)>=0},isPlainObject:function(a){if("object"!==o.type(a)||a.nodeType||o.isWindow(a))return!1;try{if(a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(b){return!1}return!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=o.trim(a),a&&(1===a.indexOf("use strict")?(b=m.createElement("script"),b.text=a,m.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":k.call(a)},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?o.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),o.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||o.guid++,f):void 0},now:Date.now,support:l}),o.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=o.type(a);return"function"===c||o.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s="sizzle"+-new Date,t=a.document,u=0,v=0,w=eb(),x=eb(),y=eb(),z=function(a,b){return a===b&&(j=!0),0},A="undefined",B=1<<31,C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=D.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},J="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",K="[\\x20\\t\\r\\n\\f]",L="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",M=L.replace("w","w#"),N="\\["+K+"*("+L+")"+K+"*(?:([*^$|!~]?=)"+K+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+M+")|)|)"+K+"*\\]",O=":("+L+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+N.replace(3,8)+")*)|.*)\\)|)",P=new RegExp("^"+K+"+|((?:^|[^\\\\])(?:\\\\.)*)"+K+"+$","g"),Q=new RegExp("^"+K+"*,"+K+"*"),R=new RegExp("^"+K+"*([>+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(O),U=new RegExp("^"+M+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L.replace("w","w*")+")"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=/'|\\/g,ab=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),bb=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{G.apply(D=H.call(t.childNodes),t.childNodes),D[t.childNodes.length].nodeType}catch(cb){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function db(a,b,d,e){var f,g,h,i,j,m,p,q,u,v;if((b?b.ownerDocument||b:t)!==l&&k(b),b=b||l,d=d||[],!a||"string"!=typeof a)return d;if(1!==(i=b.nodeType)&&9!==i)return[];if(n&&!e){if(f=Z.exec(a))if(h=f[1]){if(9===i){if(g=b.getElementById(h),!g||!g.parentNode)return d;if(g.id===h)return d.push(g),d}else if(b.ownerDocument&&(g=b.ownerDocument.getElementById(h))&&r(b,g)&&g.id===h)return d.push(g),d}else{if(f[2])return G.apply(d,b.getElementsByTagName(a)),d;if((h=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(h)),d}if(c.qsa&&(!o||!o.test(a))){if(q=p=s,u=b,v=9===i&&a,1===i&&"object"!==b.nodeName.toLowerCase()){m=ob(a),(p=b.getAttribute("id"))?q=p.replace(_,"\\$&"):b.setAttribute("id",q),q="[id='"+q+"'] ",j=m.length;while(j--)m[j]=q+pb(m[j]);u=$.test(a)&&mb(b.parentNode)||b,v=m.join(",")}if(v)try{return G.apply(d,u.querySelectorAll(v)),d}catch(w){}finally{p||b.removeAttribute("id")}}}return xb(a.replace(P,"$1"),b,d,e)}function eb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function fb(a){return a[s]=!0,a}function gb(a){var b=l.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function hb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function ib(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||B)-(~a.sourceIndex||B);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function jb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function kb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function lb(a){return fb(function(b){return b=+b,fb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function mb(a){return a&&typeof a.getElementsByTagName!==A&&a}c=db.support={},f=db.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},k=db.setDocument=function(a){var b,e=a?a.ownerDocument||a:t,g=e.defaultView;return e!==l&&9===e.nodeType&&e.documentElement?(l=e,m=e.documentElement,n=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){k()},!1):g.attachEvent&&g.attachEvent("onunload",function(){k()})),c.attributes=gb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=gb(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(e.getElementsByClassName)&&gb(function(a){return a.innerHTML="
",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=gb(function(a){return m.appendChild(a).id=s,!e.getElementsByName||!e.getElementsByName(s).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==A&&n){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ab,bb);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ab,bb);return function(a){var c=typeof a.getAttributeNode!==A&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==A?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==A&&n?b.getElementsByClassName(a):void 0},p=[],o=[],(c.qsa=Y.test(e.querySelectorAll))&&(gb(function(a){a.innerHTML="",a.querySelectorAll("[t^='']").length&&o.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||o.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll(":checked").length||o.push(":checked")}),gb(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&o.push("name"+K+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||o.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),o.push(",.*:")})),(c.matchesSelector=Y.test(q=m.webkitMatchesSelector||m.mozMatchesSelector||m.oMatchesSelector||m.msMatchesSelector))&&gb(function(a){c.disconnectedMatch=q.call(a,"div"),q.call(a,"[s!='']:x"),p.push("!=",O)}),o=o.length&&new RegExp(o.join("|")),p=p.length&&new RegExp(p.join("|")),b=Y.test(m.compareDocumentPosition),r=b||Y.test(m.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},z=b?function(a,b){if(a===b)return j=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===t&&r(t,a)?-1:b===e||b.ownerDocument===t&&r(t,b)?1:i?I.call(i,a)-I.call(i,b):0:4&d?-1:1)}:function(a,b){if(a===b)return j=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],k=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:i?I.call(i,a)-I.call(i,b):0;if(f===g)return ib(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)k.unshift(c);while(h[d]===k[d])d++;return d?ib(h[d],k[d]):h[d]===t?-1:k[d]===t?1:0},e):l},db.matches=function(a,b){return db(a,null,null,b)},db.matchesSelector=function(a,b){if((a.ownerDocument||a)!==l&&k(a),b=b.replace(S,"='$1']"),!(!c.matchesSelector||!n||p&&p.test(b)||o&&o.test(b)))try{var d=q.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return db(b,l,null,[a]).length>0},db.contains=function(a,b){return(a.ownerDocument||a)!==l&&k(a),r(a,b)},db.attr=function(a,b){(a.ownerDocument||a)!==l&&k(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!n):void 0;return void 0!==f?f:c.attributes||!n?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},db.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},db.uniqueSort=function(a){var b,d=[],e=0,f=0;if(j=!c.detectDuplicates,i=!c.sortStable&&a.slice(0),a.sort(z),j){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return i=null,a},e=db.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=db.selectors={cacheLength:50,createPseudo:fb,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ab,bb),a[3]=(a[4]||a[5]||"").replace(ab,bb),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||db.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&db.error(a[0]),a},PSEUDO:function(a){var b,c=!a[5]&&a[2];return V.CHILD.test(a[0])?null:(a[3]&&void 0!==a[4]?a[2]=a[4]:c&&T.test(c)&&(b=ob(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ab,bb).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=w[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&w(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==A&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=db.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),t=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&t){k=q[s]||(q[s]={}),j=k[a]||[],n=j[0]===u&&j[1],m=j[0]===u&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[u,n,m];break}}else if(t&&(j=(b[s]||(b[s]={}))[a])&&j[0]===u)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(t&&((l[s]||(l[s]={}))[a]=[u,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||db.error("unsupported pseudo: "+a);return e[s]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?fb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:fb(function(a){var b=[],c=[],d=g(a.replace(P,"$1"));return d[s]?fb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:fb(function(a){return function(b){return db(a,b).length>0}}),contains:fb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:fb(function(a){return U.test(a||"")||db.error("unsupported lang: "+a),a=a.replace(ab,bb).toLowerCase(),function(b){var c;do if(c=n?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===m},focus:function(a){return a===l.activeElement&&(!l.hasFocus||l.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:lb(function(){return[0]}),last:lb(function(a,b){return[b-1]}),eq:lb(function(a,b,c){return[0>c?c+b:c]}),even:lb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:lb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:lb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:lb(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function qb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=v++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[u,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[s]||(b[s]={}),(h=i[d])&&h[0]===u&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function rb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function sb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function tb(a,b,c,d,e,f){return d&&!d[s]&&(d=tb(d)),e&&!e[s]&&(e=tb(e,f)),fb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||wb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:sb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=sb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?I.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=sb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ub(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],i=g||d.relative[" "],j=g?1:0,k=qb(function(a){return a===b},i,!0),l=qb(function(a){return I.call(b,a)>-1},i,!0),m=[function(a,c,d){return!g&&(d||c!==h)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>j;j++)if(c=d.relative[a[j].type])m=[qb(rb(m),c)];else{if(c=d.filter[a[j].type].apply(null,a[j].matches),c[s]){for(e=++j;f>e;e++)if(d.relative[a[e].type])break;return tb(j>1&&rb(m),j>1&&pb(a.slice(0,j-1).concat({value:" "===a[j-2].type?"*":""})).replace(P,"$1"),c,e>j&&ub(a.slice(j,e)),f>e&&ub(a=a.slice(e)),f>e&&pb(a))}m.push(c)}return rb(m)}function vb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,i,j,k){var m,n,o,p=0,q="0",r=f&&[],s=[],t=h,v=f||e&&d.find.TAG("*",k),w=u+=null==t?1:Math.random()||.1,x=v.length;for(k&&(h=g!==l&&g);q!==x&&null!=(m=v[q]);q++){if(e&&m){n=0;while(o=a[n++])if(o(m,g,i)){j.push(m);break}k&&(u=w)}c&&((m=!o&&m)&&p--,f&&r.push(m))}if(p+=q,c&&q!==p){n=0;while(o=b[n++])o(r,s,g,i);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=E.call(j));s=sb(s)}G.apply(j,s),k&&!f&&s.length>0&&p+b.length>1&&db.uniqueSort(j)}return k&&(u=w,h=t),r};return c?fb(f):f}g=db.compile=function(a,b){var c,d=[],e=[],f=y[a+" "];if(!f){b||(b=ob(a)),c=b.length;while(c--)f=ub(b[c]),f[s]?d.push(f):e.push(f);f=y(a,vb(e,d))}return f};function wb(a,b,c){for(var d=0,e=b.length;e>d;d++)db(a,b[d],c);return c}function xb(a,b,e,f){var h,i,j,k,l,m=ob(a);if(!f&&1===m.length){if(i=m[0]=m[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&c.getById&&9===b.nodeType&&n&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(ab,bb),b)||[])[0],!b)return e;a=a.slice(i.shift().value.length)}h=V.needsContext.test(a)?0:i.length;while(h--){if(j=i[h],d.relative[k=j.type])break;if((l=d.find[k])&&(f=l(j.matches[0].replace(ab,bb),$.test(i[0].type)&&mb(b.parentNode)||b))){if(i.splice(h,1),a=f.length&&pb(i),!a)return G.apply(e,f),e;break}}}return g(a,m)(f,b,!n,e,$.test(a)&&mb(b.parentNode)||b),e}return c.sortStable=s.split("").sort(z).join("")===s,c.detectDuplicates=!!j,k(),c.sortDetached=gb(function(a){return 1&a.compareDocumentPosition(l.createElement("div"))}),gb(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||hb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&gb(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||hb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),gb(function(a){return null==a.getAttribute("disabled")})||hb(J,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),db}(a);o.find=t,o.expr=t.selectors,o.expr[":"]=o.expr.pseudos,o.unique=t.uniqueSort,o.text=t.getText,o.isXMLDoc=t.isXML,o.contains=t.contains;var u=o.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(o.isFunction(b))return o.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return o.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return o.filter(b,a,c);b=o.filter(b,a)}return o.grep(a,function(a){return g.call(b,a)>=0!==c})}o.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?o.find.matchesSelector(d,a)?[d]:[]:o.find.matches(a,o.grep(b,function(a){return 1===a.nodeType}))},o.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(o(a).filter(function(){for(b=0;c>b;b++)if(o.contains(e[b],this))return!0}));for(b=0;c>b;b++)o.find(a,e[b],d);return d=this.pushStack(c>1?o.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?o(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=o.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof o?b[0]:b,o.merge(this,o.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:m,!0)),v.test(c[1])&&o.isPlainObject(b))for(c in b)o.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=m.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=m,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):o.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(o):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),o.makeArray(a,this))};A.prototype=o.fn,y=o(m);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};o.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&o(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),o.fn.extend({has:function(a){var b=o(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(o.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?o(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&o.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?o.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(o(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(o.unique(o.merge(this.get(),o(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}o.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return o.dir(a,"parentNode")},parentsUntil:function(a,b,c){return o.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return o.dir(a,"nextSibling")},prevAll:function(a){return o.dir(a,"previousSibling")},nextUntil:function(a,b,c){return o.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return o.dir(a,"previousSibling",c)},siblings:function(a){return o.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return o.sibling(a.firstChild)},contents:function(a){return a.contentDocument||o.merge([],a.childNodes)}},function(a,b){o.fn[a]=function(c,d){var e=o.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=o.filter(d,e)),this.length>1&&(C[a]||o.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return o.each(a.match(E)||[],function(a,c){b[c]=!0}),b}o.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):o.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){o.each(b,function(b,c){var d=o.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&o.each(arguments,function(a,b){var c;while((c=o.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?o.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},o.extend({Deferred:function(a){var b=[["resolve","done",o.Callbacks("once memory"),"resolved"],["reject","fail",o.Callbacks("once memory"),"rejected"],["notify","progress",o.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return o.Deferred(function(c){o.each(b,function(b,f){var g=o.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&o.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?o.extend(a,d):d}},e={};return d.pipe=d.then,o.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&o.isFunction(a.promise)?e:0,g=1===f?a:o.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&o.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;o.fn.ready=function(a){return o.ready.promise().done(a),this},o.extend({isReady:!1,readyWait:1,holdReady:function(a){a?o.readyWait++:o.ready(!0)},ready:function(a){(a===!0?--o.readyWait:o.isReady)||(o.isReady=!0,a!==!0&&--o.readyWait>0||(H.resolveWith(m,[o]),o.fn.trigger&&o(m).trigger("ready").off("ready")))}});function I(){m.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),o.ready()}o.ready.promise=function(b){return H||(H=o.Deferred(),"complete"===m.readyState?setTimeout(o.ready):(m.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},o.ready.promise();var J=o.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===o.type(c)){e=!0;for(h in c)o.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,o.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(o(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};o.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=o.expando+Math.random()}K.uid=1,K.accepts=o.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,o.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(o.isEmptyObject(f))o.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,o.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{o.isArray(b)?d=b.concat(b.map(o.camelCase)):(e=o.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!o.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?o.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}o.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){return M.access(a,b,c)},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),o.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length; 3 | while(c--)d=g[c].name,0===d.indexOf("data-")&&(d=o.camelCase(d.slice(5)),P(f,d,e[d]));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=o.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),o.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||o.isArray(c)?d=L.access(a,b,o.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=o.queue(a,b),d=c.length,e=c.shift(),f=o._queueHooks(a,b),g=function(){o.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:o.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),o.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length",l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";l.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return m.activeElement}catch(a){}}o.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=o.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof o!==U&&o.event.triggered!==b.type?o.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],n=q=h[1],p=(h[2]||"").split(".").sort(),n&&(l=o.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=o.event.special[n]||{},k=o.extend({type:n,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&o.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(n,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),o.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],n=q=h[1],p=(h[2]||"").split(".").sort(),n){l=o.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||o.removeEvent(a,n,r.handle),delete i[n])}else for(n in i)o.event.remove(a,n+b[j],c,d,!0);o.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,p=[d||m],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||m,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+o.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[o.expando]?b:new o.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:o.makeArray(c,[b]),n=o.event.special[q]||{},e||!n.trigger||n.trigger.apply(d,c)!==!1)){if(!e&&!n.noBubble&&!o.isWindow(d)){for(i=n.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||m)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:n.bindType||q,l=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),l&&l.apply(g,c),l=k&&g[k],l&&l.apply&&o.acceptData(g)&&(b.result=l.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||n._default&&n._default.apply(p.pop(),c)!==!1||!o.acceptData(d)||k&&o.isFunction(d[q])&&!o.isWindow(d)&&(h=d[k],h&&(d[k]=null),o.event.triggered=q,d[q](),o.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=o.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=o.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=o.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((o.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?o(e,this).index(i)>=0:o.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,bb=/<([\w:]+)/,cb=/<|&#?\w+;/,db=/<(?:script|style|link)/i,eb=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/^$|\/(?:java|ecma)script/i,gb=/^true\/(.*)/,hb=/^\s*\s*$/g,ib={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ib.optgroup=ib.option,ib.tbody=ib.tfoot=ib.colgroup=ib.caption=ib.thead,ib.th=ib.td;function jb(a,b){return o.nodeName(a,"table")&&o.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function kb(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function lb(a){var b=gb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function mb(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function nb(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)o.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=o.extend({},h),M.set(b,i))}}function ob(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&o.nodeName(a,b)?o.merge([a],c):c}function pb(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}o.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=o.contains(a.ownerDocument,a);if(!(l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||o.isXMLDoc(a)))for(g=ob(h),f=ob(a),d=0,e=f.length;e>d;d++)pb(f[d],g[d]);if(b)if(c)for(f=f||ob(a),g=g||ob(h),d=0,e=f.length;e>d;d++)nb(f[d],g[d]);else nb(a,h);return g=ob(h,"script"),g.length>0&&mb(g,!i&&ob(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,n=a.length;n>m;m++)if(e=a[m],e||0===e)if("object"===o.type(e))o.merge(l,e.nodeType?[e]:e);else if(cb.test(e)){f=f||k.appendChild(b.createElement("div")),g=(bb.exec(e)||["",""])[1].toLowerCase(),h=ib[g]||ib._default,f.innerHTML=h[1]+e.replace(ab,"<$1>")+h[2],j=h[0];while(j--)f=f.lastChild;o.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===o.inArray(e,d))&&(i=o.contains(e.ownerDocument,e),f=ob(k.appendChild(e),"script"),i&&mb(f),c)){j=0;while(e=f[j++])fb.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f,g,h=o.event.special,i=0;void 0!==(c=a[i]);i++){if(o.acceptData(c)&&(f=c[L.expando],f&&(b=L.cache[f]))){if(d=Object.keys(b.events||{}),d.length)for(g=0;void 0!==(e=d[g]);g++)h[e]?o.event.remove(c,e):o.removeEvent(c,e,b.handle);L.cache[f]&&delete L.cache[f]}delete M.cache[c[M.expando]]}}}),o.fn.extend({text:function(a){return J(this,function(a){return void 0===a?o.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?o.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||o.cleanData(ob(c)),c.parentNode&&(b&&o.contains(c.ownerDocument,c)&&mb(ob(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(o.cleanData(ob(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return o.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!db.test(a)&&!ib[(bb.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ab,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(o.cleanData(ob(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,o.cleanData(ob(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,k=this.length,m=this,n=k-1,p=a[0],q=o.isFunction(p);if(q||k>1&&"string"==typeof p&&!l.checkClone&&eb.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(k&&(c=o.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=o.map(ob(c,"script"),kb),g=f.length;k>j;j++)h=c,j!==n&&(h=o.clone(h,!0,!0),g&&o.merge(f,ob(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,o.map(f,lb),j=0;g>j;j++)h=f[j],fb.test(h.type||"")&&!L.access(h,"globalEval")&&o.contains(i,h)&&(h.src?o._evalUrl&&o._evalUrl(h.src):o.globalEval(h.textContent.replace(hb,"")))}return this}}),o.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){o.fn[a]=function(a){for(var c,d=[],e=o(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),o(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qb,rb={};function sb(b,c){var d=o(c.createElement(b)).appendTo(c.body),e=a.getDefaultComputedStyle?a.getDefaultComputedStyle(d[0]).display:o.css(d[0],"display");return d.detach(),e}function tb(a){var b=m,c=rb[a];return c||(c=sb(a,b),"none"!==c&&c||(qb=(qb||o("