├── .eslintrc.js ├── .gitignore ├── README.md ├── app ├── arrays.js ├── async.js ├── bestPractices.js ├── count.js ├── flowControl.js ├── functions.js ├── logicalOperators.js ├── modules.js ├── numbers.js ├── objects.js ├── recursion.js └── regex.js └── package.json /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true, 4 | "node": true 5 | }, 6 | "globals": { 7 | "arraysAnswers": false, 8 | "asyncAnswers": false, 9 | "bestPracticesAnswers": false, 10 | "countAnswers": false, 11 | "flowControlAnswers": false, 12 | "functionsAnswers": false, 13 | "logicalOperatorsAnswers": false, 14 | "modulesAnswers": false, 15 | "numbersAnswers": false, 16 | "objectsAnswers": false, 17 | "recursionAnswers": false, 18 | "regexAnswers": false, 19 | "stringsAnswers": false, 20 | 21 | "it": false, 22 | "require": false, 23 | "describe": false, 24 | "beforeEach": false, 25 | "afterEach": false, 26 | "before": false, 27 | "after": false 28 | }, 29 | "extends": "eslint:recommended", 30 | "rules": { 31 | "accessor-pairs": "error", 32 | "array-callback-return": "error", 33 | "arrow-body-style": "error", 34 | "arrow-parens": "error", 35 | "arrow-spacing": "error", 36 | "block-spacing": [ 37 | "error", 38 | "always" 39 | ], 40 | "callback-return": "error", 41 | "camelcase": "error", 42 | "comma-spacing": [ 43 | "error", 44 | { 45 | "after": true, 46 | "before": false 47 | } 48 | ], 49 | "comma-style": [ 50 | "error", 51 | "last" 52 | ], 53 | "complexity": "error", 54 | "computed-property-spacing": [ 55 | "error", 56 | "never" 57 | ], 58 | "consistent-return": "error", 59 | "consistent-this": "error", 60 | "curly": "error", 61 | "default-case": "error", 62 | "dot-location": "error", 63 | "dot-notation": "error", 64 | "eol-last": "error", 65 | "eqeqeq": "error", 66 | "generator-star-spacing": "error", 67 | "guard-for-in": "error", 68 | "handle-callback-err": "error", 69 | "id-blacklist": "error", 70 | "id-match": "error", 71 | "indent": [ "error", 2 ], 72 | "jsx-quotes": "error", 73 | "key-spacing": [ 74 | "error", { 75 | "beforeColon": false, 76 | "afterColon": true 77 | } 78 | ], 79 | "keyword-spacing": "error", 80 | "linebreak-style": [ 81 | "error", 82 | "unix" 83 | ], 84 | "lines-around-comment": "error", 85 | "max-depth": "error", 86 | "max-len": [ "error", 120 ], 87 | "max-nested-callbacks": "error", 88 | "max-params": "error", 89 | "new-parens": "error", 90 | "newline-per-chained-call": "error", 91 | "no-alert": "error", 92 | "no-array-constructor": "error", 93 | "no-bitwise": "error", 94 | "no-caller": "error", 95 | "no-catch-shadow": "error", 96 | "no-confusing-arrow": "error", 97 | "no-continue": "error", 98 | "no-div-regex": "error", 99 | "no-duplicate-imports": "error", 100 | "no-else-return": "error", 101 | "no-empty-function": "error", 102 | "no-eq-null": "error", 103 | "no-eval": "error", 104 | "no-extend-native": "error", 105 | "no-extra-bind": "error", 106 | "no-extra-label": "error", 107 | "no-extra-parens": "warn", 108 | "no-floating-decimal": "error", 109 | "no-implicit-coercion": "error", 110 | "no-implicit-globals": "warn", 111 | "no-implied-eval": "error", 112 | "no-inner-declarations": [ 113 | "error", 114 | "functions" 115 | ], 116 | "no-invalid-this": "error", 117 | "no-iterator": "error", 118 | "no-label-var": "error", 119 | "no-labels": "error", 120 | "no-lone-blocks": "error", 121 | "no-lonely-if": "error", 122 | "no-loop-func": "error", 123 | "no-mixed-requires": "error", 124 | "no-multi-spaces": "error", 125 | "no-multi-str": "error", 126 | "no-multiple-empty-lines": "error", 127 | "no-negated-condition": "error", 128 | "no-nested-ternary": "error", 129 | "no-new": "error", 130 | "no-new-func": "error", 131 | "no-new-object": "error", 132 | "no-new-require": "error", 133 | "no-new-wrappers": "error", 134 | "no-octal-escape": "error", 135 | "no-path-concat": "error", 136 | "no-process-env": "error", 137 | "no-process-exit": "error", 138 | "no-proto": "error", 139 | "no-restricted-globals": "error", 140 | "no-restricted-imports": "error", 141 | "no-restricted-modules": "error", 142 | "no-restricted-syntax": "error", 143 | "no-return-assign": "error", 144 | "no-script-url": "error", 145 | "no-self-compare": "error", 146 | "no-sequences": "error", 147 | "no-shadow": "error", 148 | "no-shadow-restricted-names": "error", 149 | "no-spaced-func": "error", 150 | "no-sync": "error", 151 | "no-throw-literal": "error", 152 | "no-trailing-spaces": "error", 153 | "no-undef-init": "error", 154 | "no-undefined": "error", 155 | "no-underscore-dangle": "error", 156 | "no-unmodified-loop-condition": "error", 157 | "no-unneeded-ternary": "error", 158 | "no-useless-call": "error", 159 | "no-useless-concat": "error", 160 | "no-useless-constructor": "error", 161 | "no-useless-escape": "error", 162 | "no-void": "error", 163 | "no-whitespace-before-property": "error", 164 | "no-with": "error", 165 | "object-curly-spacing": "error", 166 | "one-var-declaration-per-line": "error", 167 | "operator-assignment": "error", 168 | "operator-linebreak": "error", 169 | "quotes": [ 170 | "error", 171 | "single" 172 | ], 173 | "radix": "error", 174 | "semi": "error", 175 | "semi-spacing": [ 176 | "error", 177 | { 178 | "after": true, 179 | "before": false 180 | } 181 | ], 182 | "sort-imports": "error", 183 | "sort-vars": "error", 184 | "space-before-blocks": "off", 185 | "space-before-function-paren": "off", 186 | "space-in-parens": "off", 187 | "space-infix-ops": "error", 188 | "space-unary-ops": "error", 189 | "spaced-comment": [ 190 | "error", 191 | "always" 192 | ], 193 | "strict": [ 194 | "error", 195 | "never" 196 | ], 197 | "template-curly-spacing": "error", 198 | "valid-jsdoc": "error", 199 | "wrap-iife": "error", 200 | "wrap-regex": "error", 201 | "yield-star-spacing": "error", 202 | "yoda": [ 203 | "error", 204 | "never" 205 | ] 206 | } 207 | }; 208 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JS Assessment Answers 2 | 3 | This repo contains the answers to the tests in the [js-assessment](https://github.com/rmurphey/js-assessment) repo. See the README there for instructions on how to work on these tests. -------------------------------------------------------------------------------- /app/arrays.js: -------------------------------------------------------------------------------- 1 | exports = typeof window === 'undefined' ? global : window; 2 | 3 | exports.arraysAnswers = { 4 | indexOf: function(arr, item) { 5 | 6 | /* 7 | if (Array.prototype.indexOf) { return arr.indexOf(item); } 8 | */ 9 | 10 | for (var i = 0, len = arr.length; i < len; i++) { 11 | if (arr[i] === item) { 12 | return i; 13 | } 14 | } 15 | 16 | return -1; 17 | }, 18 | 19 | sum: function(arr) { 20 | var sum = 0; 21 | 22 | for (var i = 0, len = arr.length; i < len; i++) { 23 | sum += arr[i]; 24 | } 25 | 26 | return sum; 27 | }, 28 | 29 | remove: function(arr, item) { 30 | var ret = []; 31 | 32 | for (var i = 0, len = arr.length; i < len; i++) { 33 | if (arr[i] !== item) { 34 | ret.push(arr[i]); 35 | } 36 | } 37 | 38 | return ret; 39 | }, 40 | 41 | removeWithoutCopy: function(arr, item) { 42 | var i; 43 | var len; 44 | 45 | for (i = 0, len = arr.length; i < len; i++) { 46 | if (arr[i] === item) { 47 | arr.splice(i, 1); 48 | i--; 49 | len--; 50 | } 51 | } 52 | 53 | return arr; 54 | }, 55 | 56 | append: function(arr, item) { 57 | arr.push(item); 58 | return arr; 59 | }, 60 | 61 | truncate: function(arr) { 62 | arr.pop(); 63 | return arr; 64 | }, 65 | 66 | prepend: function(arr, item) { 67 | arr.unshift(item); 68 | return arr; 69 | }, 70 | 71 | curtail: function(arr) { 72 | arr.shift(arr); 73 | return arr; 74 | }, 75 | 76 | concat: function(arr1, arr2) { 77 | return arr1.concat(arr2); 78 | }, 79 | 80 | insert: function(arr, item, index) { 81 | arr.splice(index, 0, item); 82 | return arr; 83 | }, 84 | 85 | count: function(arr, item) { 86 | var count = 0; 87 | 88 | for (var i = 0, len = arr.length; i < len; i++) { 89 | if (arr[i] === item) { 90 | count++; 91 | } 92 | } 93 | 94 | return count; 95 | }, 96 | 97 | duplicates: function(arr) { 98 | var seen = {}; 99 | var dupes = []; 100 | 101 | for (var i = 0, len = arr.length; i < len; i++) { 102 | seen[arr[i]] = seen[arr[i]] ? seen[arr[i]] + 1 : 1; 103 | } 104 | 105 | for (var item in seen) { 106 | if (seen.hasOwnProperty(item) && seen[item] > 1) { 107 | dupes.push(item); 108 | } 109 | } 110 | 111 | return dupes; 112 | }, 113 | 114 | square: function(arr) { 115 | var ret = []; 116 | 117 | for (var i = 0, len = arr.length; i < len; i++) { 118 | ret.push(arr[i] * arr[i]); 119 | } 120 | 121 | return ret; 122 | }, 123 | 124 | findAllOccurrences: function(arr, target) { 125 | var ret = []; 126 | 127 | for (var i = 0, len = arr.length; i < len; i++) { 128 | if (arr[i] === target) { 129 | ret.push(i); 130 | } 131 | } 132 | 133 | return ret; 134 | } 135 | }; 136 | -------------------------------------------------------------------------------- /app/async.js: -------------------------------------------------------------------------------- 1 | /* global $ */ 2 | exports = typeof window === 'undefined' ? global : window; 3 | 4 | exports.asyncAnswers = { 5 | async: function(value) { 6 | var dfd = $.Deferred(); 7 | setTimeout(function() { 8 | dfd.resolve(value); 9 | }, 10); 10 | return dfd.promise(); 11 | }, 12 | 13 | manipulateRemoteData: function(url) { 14 | var dfd = $.Deferred(); 15 | 16 | $.ajax(url).then(function(resp) { 17 | var people = $.map(resp.people, function(person) { 18 | return person.name; 19 | }); 20 | dfd.resolve(people.sort()); 21 | }); 22 | 23 | return dfd.promise(); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /app/bestPractices.js: -------------------------------------------------------------------------------- 1 | exports = typeof window === 'undefined' ? global : window; 2 | 3 | /** 4 | * This file defines an object with some methods. Some of these methods are 5 | * populated incorrectly; your job is to fix them. Other methods are not 6 | * populated at all; your job is to fill them out. 7 | */ 8 | exports.bestPracticesAnswers = { 9 | 10 | globals: function() { 11 | var myObject = { 12 | name: 'Jory' 13 | }; 14 | 15 | return myObject; 16 | }, 17 | 18 | parseInt: function(num) { 19 | return parseInt(num, 10); 20 | }, 21 | 22 | identity: function(val1, val2) { 23 | return val1 === val2; 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /app/count.js: -------------------------------------------------------------------------------- 1 | exports = typeof window === 'undefined' ? global : window; 2 | 3 | exports.countAnswers = { 4 | count: function (start, end) { 5 | var timeout; 6 | function doIt () { 7 | console.log(start++); // eslint-disable-line no-console 8 | 9 | if (start <= end) { 10 | timeout = setTimeout(doIt, 100); 11 | } 12 | } 13 | 14 | doIt(); 15 | 16 | return { 17 | cancel: function () { 18 | timeout && clearTimeout(timeout); 19 | } 20 | }; 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /app/flowControl.js: -------------------------------------------------------------------------------- 1 | exports = typeof window === 'undefined' ? global : window; 2 | 3 | exports.flowControlAnswers = { 4 | fizzBuzz: function(num) { 5 | 6 | // INSTRUCTIONS 7 | // write a function that receives a number as its argument; 8 | // if the number is divisible by 3, the function should return 'fizz'; 9 | // if the number is divisible by 5, the function should return 'buzz'; 10 | // if the number is divisible by 3 and 5, the function should return 11 | // 'fizzbuzz'; 12 | // 13 | // otherwise the function should return the number, or false if no number 14 | // was provided or if the value provided was not a number 15 | 16 | // make sure the value provided was a number, if not, return false 17 | if (typeof num !== 'number') { 18 | return false; 19 | } 20 | 21 | // if the number is divisible by 3 AND 5, then when divided by both, 22 | // the remainder for each operation will be zero 23 | // return 'fizzbuzz' 24 | if (num % 3 === 0 && num % 5 === 0) { 25 | return 'fizzbuzz'; 26 | } 27 | 28 | // if the number is divisible by 3, when divided by 3, the remainder is zero 29 | // return 'fizz' 30 | if (num % 3 === 0) { 31 | return 'fizz'; 32 | } 33 | 34 | // if the number is divisible by 5, when divided by 5, the remainder is zero 35 | // return 'buzz' 36 | if (num % 5 === 0) { 37 | return 'buzz'; 38 | } 39 | 40 | // if the number is not divisible by 3 or 5, i.e. has skipped all previous 41 | // conditions, return the number 42 | return num; 43 | 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /app/functions.js: -------------------------------------------------------------------------------- 1 | exports = typeof window === 'undefined' ? global : window; 2 | 3 | exports.functionsAnswers = { 4 | argsAsArray: function(fn, arr) { 5 | return fn.apply(null, arr); 6 | }, 7 | 8 | speak: function(fn, obj) { 9 | return fn.call(obj); 10 | }, 11 | 12 | functionFunction: function(str) { 13 | return function(arg) { 14 | return str + ', ' + arg; 15 | }; 16 | }, 17 | 18 | makeClosures: function(arr, fn) { 19 | var ret = []; 20 | 21 | var makeFn = function(val) { 22 | return function() { return fn(val); }; 23 | }; 24 | 25 | for (var i = 0, len = arr.length; i < len; i++) { 26 | ret.push(makeFn(arr[i])); 27 | } 28 | 29 | return ret; 30 | }, 31 | 32 | partial: function(fn, str1, str2) { 33 | return function(str3) { 34 | return fn(str1, str2, str3); 35 | }; 36 | }, 37 | 38 | useArguments: function() { 39 | var sum = 0; 40 | 41 | for (var i = 0, len = arguments.length; i < len; i++) { 42 | sum += arguments[i]; 43 | } 44 | 45 | return sum; 46 | }, 47 | 48 | callIt: function(fn) { 49 | var args = Array.prototype.slice.call(arguments, 1, arguments.length); 50 | fn.apply(null, args); 51 | }, 52 | 53 | partialUsingArguments: function(fn) { 54 | var args = Array.prototype.slice.call(arguments, 1, arguments.length); 55 | return function() { 56 | var moreArgs = args.concat(Array.prototype.slice.call(arguments)); 57 | return fn.apply(null, moreArgs); 58 | }; 59 | }, 60 | 61 | curryIt: function(fn) { 62 | function applyArguments(_fn, args) { 63 | return _fn.apply(null, args); 64 | } 65 | 66 | function getArgumentAccumulator(accumulatedArguments, expectedArgumentsCount) { 67 | return function (currentArgument) { 68 | accumulatedArguments.push(currentArgument); 69 | 70 | var allArgumentsProvided = accumulatedArguments.length === expectedArgumentsCount; 71 | 72 | if (allArgumentsProvided) { 73 | return applyArguments(fn, accumulatedArguments); 74 | } 75 | 76 | return getArgumentAccumulator(accumulatedArguments, expectedArgumentsCount); 77 | }; 78 | } 79 | 80 | return getArgumentAccumulator([], fn.length); 81 | } 82 | }; 83 | -------------------------------------------------------------------------------- /app/logicalOperators.js: -------------------------------------------------------------------------------- 1 | exports = typeof window === 'undefined' ? global : window; 2 | 3 | exports.logicalOperatorsAnswers = { 4 | or: function(a, b) { 5 | return a || b; 6 | }, 7 | 8 | and: function(a, b) { 9 | return a && b; 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /app/modules.js: -------------------------------------------------------------------------------- 1 | exports = typeof window === 'undefined' ? global : window; 2 | 3 | exports.modulesAnswers = { 4 | createModule: function(str1, str2) { 5 | return { 6 | sayIt: function() { 7 | return this.greeting + ', ' + this.name; 8 | }, 9 | 10 | name: str2, 11 | greeting: str1 12 | }; 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /app/numbers.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-bitwise */ 2 | exports = typeof window === 'undefined' ? global : window; 3 | 4 | exports.numbersAnswers = { 5 | valueAtBit: function(num, bit) { 6 | return 1 & (num >> (bit - 1)); 7 | }, 8 | 9 | base10: function(str) { 10 | return parseInt(str, 2); 11 | }, 12 | 13 | convertToBinary: function(num) { 14 | var arr = []; 15 | 16 | for (var i = 7; i > -1; i--) { 17 | arr.push( num & (1 << i) ? 1 : 0 ); 18 | } 19 | 20 | return arr.join(''); 21 | }, 22 | 23 | multiply: function(a, b) { 24 | a = adjust(a); 25 | b = adjust(b); 26 | 27 | var result = (a.adjusted * b.adjusted) / (a.multiplier * b.multiplier); 28 | 29 | return result; 30 | 31 | function adjust(num) { 32 | var exponent, multiplier; 33 | 34 | if (num < 1) { 35 | exponent = Math.floor( Math.log(num) * -1 ); 36 | multiplier = Math.pow(10, exponent); 37 | 38 | return {adjusted: num * multiplier, multiplier: multiplier}; 39 | } 40 | 41 | return {adjusted: num, multiplier: 1}; 42 | } 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /app/objects.js: -------------------------------------------------------------------------------- 1 | exports = typeof window === 'undefined' ? global : window; 2 | 3 | exports.objectsAnswers = { 4 | alterContext: function(fn, obj) { 5 | return fn.call(obj); 6 | }, 7 | 8 | alterObjects: function(constructor, greeting) { 9 | constructor.prototype.greeting = greeting; 10 | }, 11 | 12 | iterate: function(obj) { 13 | var ret = []; 14 | 15 | for (var prop in obj) { 16 | if (obj.hasOwnProperty(prop)) { 17 | ret.push(prop + ': ' + obj[prop]); 18 | } 19 | } 20 | 21 | return ret; 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /app/recursion.js: -------------------------------------------------------------------------------- 1 | exports = typeof window === 'undefined' ? global : window; 2 | 3 | exports.recursionAnswers = { 4 | listFiles: function(data, dirName) { 5 | var listOfFiles = []; 6 | var dirs = []; 7 | 8 | function processDir(dir) { 9 | var i; 10 | var len; 11 | var file; 12 | var files = dir.files; 13 | 14 | dirs.push( dir.dir ); 15 | 16 | for (i = 0, len = files.length; i < len; i++) { 17 | file = files[i]; 18 | if (typeof file === 'string') { 19 | if (!dirName || dirs.indexOf(dirName) > -1) { 20 | listOfFiles.push(files[i]); 21 | } 22 | } else { 23 | processDir(files[i]); 24 | } 25 | } 26 | 27 | dirs.pop(); 28 | } 29 | 30 | processDir(data); 31 | 32 | 33 | return listOfFiles; 34 | }, 35 | 36 | permute: function(arr) { 37 | // http://stackoverflow.com/a/11509565/54468 38 | var temp = []; 39 | var answer = []; 40 | 41 | function logResult() { 42 | answer.push( 43 | // make a copy of temp using .slice() 44 | // so we can continue to work with temp 45 | temp.slice() 46 | ); 47 | } 48 | 49 | function doIt() { 50 | var i; 51 | var len; 52 | var item; 53 | 54 | for (i = 0, len = arr.length; i < len; i++) { 55 | // remove the item at index i 56 | item = arr.splice(i, 1)[0]; 57 | 58 | // add that item to the array we're building up 59 | temp.push(item); 60 | 61 | if (arr.length) { 62 | // if there's still anything left in the array, 63 | // recurse over what's left 64 | doIt(); 65 | } else { 66 | // otherwise, log the result and move on 67 | logResult(); 68 | } 69 | 70 | // restore the item we removed at index i 71 | // and remove it from our temp array 72 | arr.splice(i, 0, item); 73 | temp.pop(); 74 | } 75 | 76 | return answer; 77 | } 78 | 79 | return doIt(); 80 | } 81 | }; 82 | -------------------------------------------------------------------------------- /app/regex.js: -------------------------------------------------------------------------------- 1 | exports = typeof window === 'undefined' ? global : window; 2 | 3 | exports.regexAnswers = { 4 | containsNumber: function(str) { 5 | return (/\d/).test(str); 6 | }, 7 | 8 | containsRepeatingLetter: function(str) { 9 | return (/([A-Za-z])\1/).test(str); 10 | }, 11 | 12 | endsWithVowel: function(str) { 13 | return (/[aeiou]$/i).test(str); 14 | }, 15 | 16 | captureThreeNumbers: function(str) { 17 | var matches = (/\d{3}/).exec(str); 18 | return matches ? matches[0] : false; 19 | }, 20 | 21 | matchesPattern: function(str) { 22 | return (/^\d{3}-\d{3}-\d{4}$/).test(str); 23 | }, 24 | 25 | isUSD: function(str) { 26 | return (/^\$\d{1,3}(,\d{3})*(\.\d{2})?$/).test(str); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "js-assessment-answers", 3 | "version": "1.0.0", 4 | "description": "This repo contains the answers to the tests in the [js-assessment](https://github.com/rmurphey/js-assessment) repo. See the README there for instructions on how to work on these tests.", 5 | "scripts": { 6 | "lint": "eslint --quiet app", 7 | "lint-warn": "eslint app" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/rmurphey/js-assessment-answers.git" 12 | }, 13 | "author": "Rebecca Murphey", 14 | "bugs": { 15 | "url": "https://github.com/rmurphey/js-assessment-answers/issues" 16 | }, 17 | "homepage": "https://github.com/rmurphey/js-assessment#readme", 18 | "devDependencies": { 19 | "eslint": "^2.8.0", 20 | "ghooks": "^1.2.1" 21 | }, 22 | "config": { 23 | "ghooks": { 24 | "pre-commit": "npm run lint" 25 | } 26 | } 27 | } 28 | --------------------------------------------------------------------------------