diff --git a/01_helloWorld/solution/helloWorld-solution.js b/01_helloWorld/solution/helloWorld-solution.js new file mode 100644 index 0000000..002f305 --- /dev/null +++ b/01_helloWorld/solution/helloWorld-solution.js @@ -0,0 +1,5 @@ +const helloWorld = function () { + return 'Hello, World!'; +}; + +module.exports = helloWorld; diff --git a/01_helloWorld/solution/helloWorld-solution.spec.js b/01_helloWorld/solution/helloWorld-solution.spec.js new file mode 100644 index 0000000..364645d --- /dev/null +++ b/01_helloWorld/solution/helloWorld-solution.spec.js @@ -0,0 +1,7 @@ +const helloWorld = require('./helloWorld-solution'); + +describe('Hello World', function () { + test('says "Hello, World!"', function () { + expect(helloWorld()).toEqual('Hello, World!'); + }); +}); diff --git a/02_repeatString/solution/repeatString-solution.js b/02_repeatString/solution/repeatString-solution.js new file mode 100644 index 0000000..e8ea93e --- /dev/null +++ b/02_repeatString/solution/repeatString-solution.js @@ -0,0 +1,10 @@ +const repeatString = function (word, times) { + if (times < 0) return 'ERROR'; + let string = ''; + for (let i = 0; i < times; i++) { + string += word; + } + return string; +}; + +module.exports = repeatString; diff --git a/02_repeatString/solution/repeatString-solution.spec.js b/02_repeatString/solution/repeatString-solution.spec.js new file mode 100644 index 0000000..299874b --- /dev/null +++ b/02_repeatString/solution/repeatString-solution.spec.js @@ -0,0 +1,41 @@ +const repeatString = require('./repeatString-solution'); + +describe('repeatString', () => { + test('repeats the string', () => { + expect(repeatString('hey', 3)).toEqual('heyheyhey'); + }); + test.skip('repeats the string many times', () => { + expect(repeatString('hey', 10)).toEqual( + 'heyheyheyheyheyheyheyheyheyhey' + ); + }); + test.skip('repeats the string 1 times', () => { + expect(repeatString('hey', 1)).toEqual('hey'); + }); + test.skip('repeats the string 0 times', () => { + expect(repeatString('hey', 0)).toEqual(''); + }); + test.skip('returns ERROR with negative numbers', () => { + expect(repeatString('hey', -1)).toEqual('ERROR'); + }); + test.skip('repeats the string a random amount of times', function () { + /*The number is generated by using Math.random to get a value from between + 0 to 1, when this is multiplied by 1000 and rounded down with Math.floor it + equals a number between 0 to 999 (this number will change everytime you run + the test).*/ + + // DO NOT use Math.floor(Math.random() * 1000) in your code, + // this test generates a random number, then passes it into your code with a function parameter. + // If this doesn't make sense, you should go read about functions here: https://www.theodinproject.com/paths/foundations/courses/foundations/lessons/fundamentals-part-3 + const number = Math.floor(Math.random() * 1000); + /*The .match(/((hey))/g).length is a regex that will count the number of heys + in the result, which if your function works correctly will equal the number that + was randomaly generated. */ + expect(repeatString('hey', number).match(/((hey))/g).length).toEqual( + number + ); + }); + test.skip('works with blank strings', () => { + expect(repeatString('', 10)).toEqual(''); + }); +}); diff --git a/03_reverseString/solution/reverseString-solution.js b/03_reverseString/solution/reverseString-solution.js new file mode 100644 index 0000000..7aee226 --- /dev/null +++ b/03_reverseString/solution/reverseString-solution.js @@ -0,0 +1,5 @@ +const reverseString = function (string) { + return string.split('').reverse().join(''); +}; + +module.exports = reverseString; diff --git a/03_reverseString/solution/reverseString-solution.spec.js b/03_reverseString/solution/reverseString-solution.spec.js new file mode 100644 index 0000000..94b2624 --- /dev/null +++ b/03_reverseString/solution/reverseString-solution.spec.js @@ -0,0 +1,18 @@ +const reverseString = require('./reverseString-solution'); + +describe('reverseString', () => { + test('reverses single word', () => { + expect(reverseString('hello')).toEqual('olleh'); + }); + + test.skip('reverses multiple words', () => { + expect(reverseString('hello there')).toEqual('ereht olleh'); + }); + + test.skip('works with numbers and punctuation', () => { + expect(reverseString('123! abc!')).toEqual('!cba !321'); + }); + test.skip('works with blank strings', () => { + expect(reverseString('')).toEqual(''); + }); +}); diff --git a/04_removeFromArray/solution/removeFromArray-solution.js b/04_removeFromArray/solution/removeFromArray-solution.js new file mode 100644 index 0000000..7399ed8 --- /dev/null +++ b/04_removeFromArray/solution/removeFromArray-solution.js @@ -0,0 +1,31 @@ +// we have 2 solutions here, an easier one and a more advanced one. +// The easiest way to get an array of all of the arguments that are passed to a function +// is using the rest operator. If this is unfamiliar to you look it up! +const removeFromArray = function (...args) { + // the very first item in our list of arguments is the array, we pull it out with args[0] + const array = args[0]; + // create a new empty array + const newArray = []; + // use forEach to go through the array + array.forEach((item) => { + // push every element into the new array + // UNLESS it is included in the function arguments + // so we create a new array with every item, except those that should be removed + if (!args.includes(item)) { + newArray.push(item); + } + }); + // and return that array + return newArray; +}; + +// A simpler, but more advanced way to do it is to use the 'filter' function, +// which basically does what we did with the forEach above. + +// var removeFromArray = function(...args) { +// const array = args[0] +// return array.filter(val => !args.includes(val)) +// } +// + +module.exports = removeFromArray; diff --git a/04_removeFromArray/solution/removeFromArray-solution.spec.js b/04_removeFromArray/solution/removeFromArray-solution.spec.js new file mode 100644 index 0000000..bc1eb1a --- /dev/null +++ b/04_removeFromArray/solution/removeFromArray-solution.spec.js @@ -0,0 +1,28 @@ +const removeFromArray = require('./removeFromArray-solution'); + +describe('removeFromArray', () => { + test('removes a single value', () => { + expect(removeFromArray([1, 2, 3, 4], 3)).toEqual([1, 2, 4]); + }); + test.skip('removes multiple values', () => { + expect(removeFromArray([1, 2, 3, 4], 3, 2)).toEqual([1, 4]); + }); + test.skip('ignores non present values', () => { + expect(removeFromArray([1, 2, 3, 4], 7, 'tacos')).toEqual([1, 2, 3, 4]); + }); + test.skip('ignores non present values, but still works', () => { + expect(removeFromArray([1, 2, 3, 4], 7, 2)).toEqual([1, 3, 4]); + }); + test.skip('can remove all values', () => { + expect(removeFromArray([1, 2, 3, 4], 1, 2, 3, 4)).toEqual([]); + }); + test.skip('works with strings', () => { + expect(removeFromArray(['hey', 2, 3, 'ho'], 'hey', 3)).toEqual([ + 2, + 'ho', + ]); + }); + test.skip('only removes same type', () => { + expect(removeFromArray([1, 2, 3], '1', 3)).toEqual([1, 2]); + }); +}); diff --git a/05_sumAll/solution/sumAll-solution.js b/05_sumAll/solution/sumAll-solution.js new file mode 100644 index 0000000..9d95b64 --- /dev/null +++ b/05_sumAll/solution/sumAll-solution.js @@ -0,0 +1,16 @@ +const sumAll = function (min, max) { + if (!Number.isInteger(min) || !Number.isInteger(max)) return 'ERROR'; + if (min < 0 || max < 0) return 'ERROR'; + if (min > max) { + const temp = min; + min = max; + max = temp; + } + let sum = 0; + for (let i = min; i < max + 1; i++) { + sum += i; + } + return sum; +}; + +module.exports = sumAll; diff --git a/05_sumAll/solution/sumAll-solution.spec.js b/05_sumAll/solution/sumAll-solution.spec.js new file mode 100644 index 0000000..ba30f62 --- /dev/null +++ b/05_sumAll/solution/sumAll-solution.spec.js @@ -0,0 +1,22 @@ +const sumAll = require('./sumAll-solution'); + +describe('sumAll', () => { + test('sums numbers within the range', () => { + expect(sumAll(1, 4)).toEqual(10); + }); + test.skip('works with large numbers', () => { + expect(sumAll(1, 4000)).toEqual(8002000); + }); + test.skip('works with larger number first', () => { + expect(sumAll(123, 1)).toEqual(7626); + }); + test.skip('returns ERROR with negative numbers', () => { + expect(sumAll(-10, 4)).toEqual('ERROR'); + }); + test.skip('returns ERROR with non-number parameters', () => { + expect(sumAll(10, '90')).toEqual('ERROR'); + }); + test.skip('returns ERROR with non-number parameters', () => { + expect(sumAll(10, [90, 1])).toEqual('ERROR'); + }); +}); diff --git a/06_leapYears/solution/leapYears-solution.js b/06_leapYears/solution/leapYears-solution.js new file mode 100644 index 0000000..31898b7 --- /dev/null +++ b/06_leapYears/solution/leapYears-solution.js @@ -0,0 +1,5 @@ +const leapYears = function (year) { + return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0); +}; + +module.exports = leapYears; diff --git a/06_leapYears/solution/leapYears-solution.spec.js b/06_leapYears/solution/leapYears-solution.spec.js new file mode 100644 index 0000000..bcc422c --- /dev/null +++ b/06_leapYears/solution/leapYears-solution.spec.js @@ -0,0 +1,22 @@ +const leapYears = require('./leapYears-solution'); + +describe('leapYears', () => { + test('works with non century years', () => { + expect(leapYears(1996)).toBe(true); + }); + test.skip('works with non century years', () => { + expect(leapYears(1997)).toBe(false); + }); + test.skip('works with ridiculously futuristic non century years', () => { + expect(leapYears(34992)).toBe(true); + }); + test.skip('works with century years', () => { + expect(leapYears(1900)).toBe(false); + }); + test.skip('works with century years', () => { + expect(leapYears(1600)).toBe(true); + }); + test.skip('works with century years', () => { + expect(leapYears(700)).toBe(false); + }); +}); diff --git a/07_tempConversion/solution/tempConversion-solution.js b/07_tempConversion/solution/tempConversion-solution.js new file mode 100644 index 0000000..a5fad55 --- /dev/null +++ b/07_tempConversion/solution/tempConversion-solution.js @@ -0,0 +1,12 @@ +const ftoc = function (f) { + return Math.round((f - 32) * (5 / 9) * 10) / 10; +}; + +const ctof = function (c) { + return Math.round(((c * 9) / 5 + 32) * 10) / 10; +}; + +module.exports = { + ftoc, + ctof, +}; diff --git a/07_tempConversion/solution/tempConversion-solution.spec.js b/07_tempConversion/solution/tempConversion-solution.spec.js new file mode 100644 index 0000000..001351d --- /dev/null +++ b/07_tempConversion/solution/tempConversion-solution.spec.js @@ -0,0 +1,25 @@ +const { ftoc, ctof } = require('./tempConversion-solution'); + +describe('ftoc', () => { + test('works', () => { + expect(ftoc(32)).toEqual(0); + }); + test.skip('rounds to 1 decimal', () => { + expect(ftoc(100)).toEqual(37.8); + }); + test.skip('works with negatives', () => { + expect(ftoc(-100)).toEqual(-73.3); + }); +}); + +describe('ctof', () => { + test.skip('works', () => { + expect(ctof(0)).toEqual(32); + }); + test.skip('rounds to 1 decimal', () => { + expect(ctof(73.2)).toEqual(163.8); + }); + test.skip('works with negatives', () => { + expect(ctof(-10)).toEqual(14); + }); +}); diff --git a/08_calculator/solution/calculator-solution.js b/08_calculator/solution/calculator-solution.js new file mode 100644 index 0000000..ea9874a --- /dev/null +++ b/08_calculator/solution/calculator-solution.js @@ -0,0 +1,48 @@ +const add = function (a, b) { + return a + b; +}; + +const subtract = function (a, b) { + return a - b; +}; + +const sum = function (array) { + return array.reduce((total, current) => total + current, 0); +}; + +const multiply = function (array) { + return array.length + ? array.reduce((accumulator, nextItem) => accumulator * nextItem) + : 0; +}; + +const power = function (a, b) { + return Math.pow(a, b); +}; + +const factorial = function (n) { + if (n === 0) return 1; + let product = 1; + for (let i = n; i > 0; i--) { + product *= i; + } + return product; +}; + +// This is another implementation of Factorial that uses recursion +// THANKS to @ThirtyThreeB! +const recursiveFactorial = function (n) { + if (n === 0) { + return 1; + } + return n * recursiveFactorial(n - 1); +}; + +module.exports = { + add, + subtract, + sum, + multiply, + power, + factorial, +}; diff --git a/08_calculator/solution/calculator-solution.spec.js b/08_calculator/solution/calculator-solution.spec.js new file mode 100644 index 0000000..3356e00 --- /dev/null +++ b/08_calculator/solution/calculator-solution.spec.js @@ -0,0 +1,77 @@ +const calculator = require('./calculator-solution'); + +describe('add', () => { + test('adds 0 and 0', () => { + expect(calculator.add(0, 0)).toBe(0); + }); + + test.skip('adds 2 and 2', () => { + expect(calculator.add(2, 2)).toBe(4); + }); + + test.skip('adds positive numbers', () => { + expect(calculator.add(2, 6)).toBe(8); + }); +}); + +describe('subtract', () => { + test.skip('subtracts numbers', () => { + expect(calculator.subtract(10, 4)).toBe(6); + }); +}); + +describe('sum', () => { + test.skip('computes the sum of an empty array', () => { + expect(calculator.sum([])).toBe(0); + }); + + test.skip('computes the sum of an array of one number', () => { + expect(calculator.sum([7])).toBe(7); + }); + + test.skip('computes the sum of an array of two numbers', () => { + expect(calculator.sum([7, 11])).toBe(18); + }); + + test.skip('computes the sum of an array of many numbers', () => { + expect(calculator.sum([1, 3, 5, 7, 9])).toBe(25); + }); +}); + +describe('multiply', () => { + test.skip('multiplies two numbers', () => { + expect(calculator.multiply([2, 4])).toBe(8); + }); + + test.skip('multiplies several numbers', () => { + expect(calculator.multiply([2, 4, 6, 8, 10, 12, 14])).toBe(645120); + }); +}); + +describe('power', () => { + test.skip('raises one number to the power of another number', () => { + expect(calculator.power(4, 3)).toBe(64); // 4 to third power is 64 + }); +}); + +describe('factorial', () => { + test.skip('computes the factorial of 0', () => { + expect(calculator.factorial(0)).toBe(1); // 0! = 1 + }); + + test.skip('computes the factorial of 1', () => { + expect(calculator.factorial(1)).toBe(1); + }); + + test.skip('computes the factorial of 2', () => { + expect(calculator.factorial(2)).toBe(2); + }); + + test.skip('computes the factorial of 5', () => { + expect(calculator.factorial(5)).toBe(120); + }); + + test.skip('computes the factorial of 10', () => { + expect(calculator.factorial(10)).toBe(3628800); + }); +}); diff --git a/09_palindromes/solution/palindromes-solution.js b/09_palindromes/solution/palindromes-solution.js new file mode 100644 index 0000000..ffd5dbf --- /dev/null +++ b/09_palindromes/solution/palindromes-solution.js @@ -0,0 +1,6 @@ +const palindromes = function (string) { + processedString = string.toLowerCase().replace(/[^a-z]/g, ''); + return processedString.split('').reverse().join('') == processedString; +}; + +module.exports = palindromes; diff --git a/09_palindromes/solution/palindromes-solution.spec.js b/09_palindromes/solution/palindromes-solution.spec.js new file mode 100644 index 0000000..afcb47a --- /dev/null +++ b/09_palindromes/solution/palindromes-solution.spec.js @@ -0,0 +1,24 @@ +const palindromes = require('./palindromes-solution'); + +describe('palindromes', () => { + test('works with single words', () => { + expect(palindromes('racecar')).toBe(true); + }); + test.skip('works with punctuation ', () => { + expect(palindromes('racecar!')).toBe(true); + }); + test.skip('works with upper-case letters ', () => { + expect(palindromes('Racecar!')).toBe(true); + }); + test.skip('works with multiple words', () => { + expect(palindromes('A car, a man, a maraca.')).toBe(true); + }); + test.skip('works with multiple words', () => { + expect( + palindromes('Animal loots foliated detail of stool lamina.') + ).toBe(true); + }); + test.skip("doesn't just always return true", () => { + expect(palindromes('ZZZZ car, a man, a maraca.')).toBe(false); + }); +}); diff --git a/10_fibonacci/solution/fibonacci-solution.js b/10_fibonacci/solution/fibonacci-solution.js new file mode 100644 index 0000000..9f9a523 --- /dev/null +++ b/10_fibonacci/solution/fibonacci-solution.js @@ -0,0 +1,14 @@ +const fibonacci = function (count) { + if (count < 0) return 'OOPS'; + if (count === 0) return 0; + let a = 0; + let b = 1; + for (let i = 1; i < count; i++) { + const temp = b; + b = a + b; + a = temp; + } + return b; +}; + +module.exports = fibonacci; diff --git a/10_fibonacci/solution/fibonacci-solution.spec.js b/10_fibonacci/solution/fibonacci-solution.spec.js new file mode 100644 index 0000000..997f30d --- /dev/null +++ b/10_fibonacci/solution/fibonacci-solution.spec.js @@ -0,0 +1,31 @@ +const fibonacci = require('./fibonacci-solution'); + +describe('fibonacci', () => { + test('4th fibonacci number is 3', () => { + expect(fibonacci(4)).toBe(3); + }); + test.skip('6th fibonacci number is 8', () => { + expect(fibonacci(6)).toBe(8); + }); + test.skip('10th fibonacci number is 55', () => { + expect(fibonacci(10)).toBe(55); + }); + test.skip('15th fibonacci number is 610', () => { + expect(fibonacci(15)).toBe(610); + }); + test.skip('25th fibonacci number is 75025', () => { + expect(fibonacci(25)).toBe(75025); + }); + test.skip("doesn't accept negatives", () => { + expect(fibonacci(-25)).toBe('OOPS'); + }); + test.skip('DOES accept strings', () => { + expect(fibonacci('1')).toBe(1); + }); + test.skip('DOES accept strings', () => { + expect(fibonacci('2')).toBe(1); + }); + test.skip('DOES accept strings', () => { + expect(fibonacci('8')).toBe(21); + }); +}); diff --git a/11_getTheTitles/solution/getTheTitles-solution.js b/11_getTheTitles/solution/getTheTitles-solution.js new file mode 100644 index 0000000..ebcf404 --- /dev/null +++ b/11_getTheTitles/solution/getTheTitles-solution.js @@ -0,0 +1,5 @@ +const getTheTitles = function (array) { + return array.map((book) => book.title); +}; + +module.exports = getTheTitles; diff --git a/11_getTheTitles/solution/getTheTitles-solution.spec.js b/11_getTheTitles/solution/getTheTitles-solution.spec.js new file mode 100644 index 0000000..e2dc20d --- /dev/null +++ b/11_getTheTitles/solution/getTheTitles-solution.spec.js @@ -0,0 +1,18 @@ +const getTheTitles = require('./getTheTitles-solution'); + +describe('getTheTitles', () => { + const books = [ + { + title: 'Book', + author: 'Name', + }, + { + title: 'Book2', + author: 'Name2', + }, + ]; + + test('gets titles', () => { + expect(getTheTitles(books)).toEqual(['Book', 'Book2']); + }); +}); diff --git a/12_findTheOldest/solution/findTheOldest-solution.js b/12_findTheOldest/solution/findTheOldest-solution.js new file mode 100644 index 0000000..d25a7ff --- /dev/null +++ b/12_findTheOldest/solution/findTheOldest-solution.js @@ -0,0 +1,19 @@ +const findTheOldest = function (array) { + return array.reduce((oldest, currentPerson) => { + const oldestAge = getAge(oldest.yearOfBirth, oldest.yearOfDeath); + const currentAge = getAge( + currentPerson.yearOfBirth, + currentPerson.yearOfDeath + ); + return oldestAge < currentAge ? currentPerson : oldest; + }); +}; + +const getAge = function (birth, death) { + if (!death) { + death = new Date().getFullYear(); + } + return death - birth; +}; + +module.exports = findTheOldest; diff --git a/12_findTheOldest/solution/findTheOldest-solution.spec.js b/12_findTheOldest/solution/findTheOldest-solution.spec.js new file mode 100644 index 0000000..2a33aff --- /dev/null +++ b/12_findTheOldest/solution/findTheOldest-solution.spec.js @@ -0,0 +1,62 @@ +const findTheOldest = require('./findTheOldest-solution'); + +describe('findTheOldest', () => { + test('finds the oldest person!', () => { + const people = [ + { + name: 'Carly', + yearOfBirth: 1942, + yearOfDeath: 1970, + }, + { + name: 'Ray', + yearOfBirth: 1962, + yearOfDeath: 2011, + }, + { + name: 'Jane', + yearOfBirth: 1912, + yearOfDeath: 1941, + }, + ]; + expect(findTheOldest(people).name).toBe('Ray'); + }); + test.skip('finds the oldest person if someone is still living', () => { + const people = [ + { + name: 'Carly', + yearOfBirth: 2018, + }, + { + name: 'Ray', + yearOfBirth: 1962, + yearOfDeath: 2011, + }, + { + name: 'Jane', + yearOfBirth: 1912, + yearOfDeath: 1941, + }, + ]; + expect(findTheOldest(people).name).toBe('Ray'); + }); + test.skip('finds the oldest person if the OLDEST is still living', () => { + const people = [ + { + name: 'Carly', + yearOfBirth: 1066, + }, + { + name: 'Ray', + yearOfBirth: 1962, + yearOfDeath: 2011, + }, + { + name: 'Jane', + yearOfBirth: 1912, + yearOfDeath: 1941, + }, + ]; + expect(findTheOldest(people).name).toBe('Carly'); + }); +}); diff --git a/13_caesar/solution/caesar-solution.js b/13_caesar/solution/caesar-solution.js new file mode 100644 index 0000000..fed2bdf --- /dev/null +++ b/13_caesar/solution/caesar-solution.js @@ -0,0 +1,26 @@ +const caesar = function (string, shift) { + return string + .split('') + .map((char) => shiftChar(char, shift)) + .join(''); +}; + +const codeSet = (code) => (code < 97 ? 65 : 97); + +// this function is just a fancy way of doing % so that it works with negative numbers +// see this link for details: +// https://stackoverflow.com/questions/4467539/javascript-modulo-gives-a-negative-result-for-negative-numbers +const mod = (n, m) => ((n % m) + m) % m; + +const shiftChar = (char, shift) => { + const code = char.charCodeAt(); + + if ((code >= 65 && code <= 90) || (code >= 97 && code <= 122)) { + return String.fromCharCode( + mod(code + shift - codeSet(code), 26) + codeSet(code) + ); + } + return char; +}; + +module.exports = caesar; diff --git a/13_caesar/solution/caesar-solution.spec.js b/13_caesar/solution/caesar-solution.spec.js new file mode 100644 index 0000000..68902ad --- /dev/null +++ b/13_caesar/solution/caesar-solution.spec.js @@ -0,0 +1,23 @@ +const caesar = require('./caesar-solution'); + +test('works with single letters', () => { + expect(caesar('A', 1)).toBe('B'); +}); +test.skip('works with words', () => { + expect(caesar('Aaa', 1)).toBe('Bbb'); +}); +test.skip('works with phrases', () => { + expect(caesar('Hello, World!', 5)).toBe('Mjqqt, Btwqi!'); +}); +test.skip('works with negative shift', () => { + expect(caesar('Mjqqt, Btwqi!', -5)).toBe('Hello, World!'); +}); +test.skip('wraps', () => { + expect(caesar('Z', 1)).toBe('A'); +}); +test.skip('works with large shift factors', () => { + expect(caesar('Hello, World!', 75)).toBe('Ebiil, Tloia!'); +}); +test.skip('works with large negative shift factors', () => { + expect(caesar('Hello, World!', -29)).toBe('Ebiil, Tloia!'); +});