From 72e20f12ead8c2999f093a5cdd87122c05b8f955 Mon Sep 17 00:00:00 2001 From: NetMan <13informatyka14@gmail.com> Date: Fri, 5 Jan 2024 20:11:55 +0100 Subject: [PATCH] Initial commit, files from default-js-exercises --- 01_helloWorld/README.md | 50 +++++++++++++++++++ 01_helloWorld/helloWorld.js | 5 ++ 01_helloWorld/helloWorld.spec.js | 7 +++ 01_helloWorld/solution/helloWorld-solution.js | 5 ++ .../solution/helloWorld-solution.spec.js | 7 +++ 02_repeatString/README.md | 29 +++++++++++ 02_repeatString/repeatString.js | 6 +++ 02_repeatString/repeatString.spec.js | 37 ++++++++++++++ .../solution/repeatString-solution.js | 10 ++++ .../solution/repeatString-solution.spec.js | 39 +++++++++++++++ 03_reverseString/README.md | 13 +++++ 03_reverseString/reverseString.js | 6 +++ 03_reverseString/reverseString.spec.js | 18 +++++++ .../solution/reverseString-solution.js | 5 ++ .../solution/reverseString-solution.spec.js | 18 +++++++ 04_removeFromArray/README.md | 16 ++++++ 04_removeFromArray/removeFromArray.js | 6 +++ 04_removeFromArray/removeFromArray.spec.js | 25 ++++++++++ .../solution/removeFromArray-solution.js | 28 +++++++++++ .../solution/removeFromArray-solution.spec.js | 25 ++++++++++ 05_sumAll/README.md | 17 +++++++ 05_sumAll/solution/sumAll-solution.js | 21 ++++++++ 05_sumAll/solution/sumAll-solution.spec.js | 25 ++++++++++ 05_sumAll/sumAll.js | 6 +++ 05_sumAll/sumAll.spec.js | 22 ++++++++ 06_leapYears/README.md | 16 ++++++ 06_leapYears/leapYears.js | 6 +++ 06_leapYears/leapYears.spec.js | 22 ++++++++ 06_leapYears/solution/leapYears-solution.js | 5 ++ .../solution/leapYears-solution.spec.js | 22 ++++++++ 07_tempConversion/README.md | 17 +++++++ .../solution/tempConversion-solution.js | 12 +++++ .../solution/tempConversion-solution.spec.js | 28 +++++++++++ 07_tempConversion/tempConversion.js | 11 ++++ 07_tempConversion/tempConversion.spec.js | 25 ++++++++++ README.md | 38 ++++++++++++++ 36 files changed, 648 insertions(+) create mode 100644 01_helloWorld/README.md create mode 100644 01_helloWorld/helloWorld.js create mode 100644 01_helloWorld/helloWorld.spec.js create mode 100644 01_helloWorld/solution/helloWorld-solution.js create mode 100644 01_helloWorld/solution/helloWorld-solution.spec.js create mode 100644 02_repeatString/README.md create mode 100644 02_repeatString/repeatString.js create mode 100644 02_repeatString/repeatString.spec.js create mode 100644 02_repeatString/solution/repeatString-solution.js create mode 100644 02_repeatString/solution/repeatString-solution.spec.js create mode 100644 03_reverseString/README.md create mode 100644 03_reverseString/reverseString.js create mode 100644 03_reverseString/reverseString.spec.js create mode 100644 03_reverseString/solution/reverseString-solution.js create mode 100644 03_reverseString/solution/reverseString-solution.spec.js create mode 100644 04_removeFromArray/README.md create mode 100644 04_removeFromArray/removeFromArray.js create mode 100644 04_removeFromArray/removeFromArray.spec.js create mode 100644 04_removeFromArray/solution/removeFromArray-solution.js create mode 100644 04_removeFromArray/solution/removeFromArray-solution.spec.js create mode 100644 05_sumAll/README.md create mode 100644 05_sumAll/solution/sumAll-solution.js create mode 100644 05_sumAll/solution/sumAll-solution.spec.js create mode 100644 05_sumAll/sumAll.js create mode 100644 05_sumAll/sumAll.spec.js create mode 100644 06_leapYears/README.md create mode 100644 06_leapYears/leapYears.js create mode 100644 06_leapYears/leapYears.spec.js create mode 100644 06_leapYears/solution/leapYears-solution.js create mode 100644 06_leapYears/solution/leapYears-solution.spec.js create mode 100644 07_tempConversion/README.md create mode 100644 07_tempConversion/solution/tempConversion-solution.js create mode 100644 07_tempConversion/solution/tempConversion-solution.spec.js create mode 100644 07_tempConversion/tempConversion.js create mode 100644 07_tempConversion/tempConversion.spec.js create mode 100644 README.md diff --git a/01_helloWorld/README.md b/01_helloWorld/README.md new file mode 100644 index 0000000..d4b267e --- /dev/null +++ b/01_helloWorld/README.md @@ -0,0 +1,50 @@ +# Exercise 01 - Hello World + +The main purpose of this exercise is to walk you through the process of running the tests and make sure everything is set up and running correctly. + +In this directory you will find 2 other files: + 1. `helloWorld.js` + 2. `helloWorld.spec.js` + +This setup should be the same for all of the exercises. The plain javascript file is where you'll write your code, and the `spec` file contains the tests that verify your code is functional. + +Let's look at the spec file first: +```javascript +const helloWorld = require('./helloWorld'); + +describe('Hello World', function() { + test('says "Hello, World!"', function() { + expect(helloWorld()).toEqual('Hello, World!'); + }); +}); +``` +At the very top of the file we use `require()` to import the code from the javascript file (`helloWorld.js`) so that we can test it. + +The next block (`describe()`) is the body of the test. Basically, all it's doing is running your code and testing to see if the output is correct. The `test()` function describes what should be happening in plain english and then includes the `expect()` function. For this simple example it should be pretty simple to read. + +For now you do not need to worry about how to write tests, but you should try to get comfortable enough with the syntax to figure out what the tests are asking you to do. Go ahead and run the tests by entering `npm test helloWorld.spec.js` in the terminal and watch it fail. The output from that command should tell you exactly what went wrong with your code. In this case, running the `helloWorld()` function should return the phrase 'Hello, World!' but instead it returns an empty string... + +so let's look at the javascript file: +```javascript +const helloWorld = function() { + return '' +} + +module.exports = helloWorld +``` +In this file we have a simple function called helloWorld that returns an empty string... which is exactly what our test was complaining about. The `module.exports` on the last line is how we export the function so that it can be imported with `require()` in the spec file. + +Go ahead and see if you can make the test pass by editing the return value of the function, and then running the test file again. + +Just to make sure, in case you're confused at this point, the test is telling you that running the function `helloWorld` should return the phrase `Hello, World!`. Punctuation and capitalization definitely matter here, so double check that if the test still isn't passing. + +This is what the final function should look like: +```javascript +const helloWorld = function() { + return 'Hello, World!' +} + +module.exports = helloWorld +``` + +For the most part we've set up these tests in such a way that you only have to write the code being tested. You should not have to worry about importing or exporting anything at this stage.. so just work around that bit of the code and write what it takes to make them pass! diff --git a/01_helloWorld/helloWorld.js b/01_helloWorld/helloWorld.js new file mode 100644 index 0000000..df27036 --- /dev/null +++ b/01_helloWorld/helloWorld.js @@ -0,0 +1,5 @@ +const helloWorld = function() { + return '' +}; + +module.exports = helloWorld; diff --git a/01_helloWorld/helloWorld.spec.js b/01_helloWorld/helloWorld.spec.js new file mode 100644 index 0000000..e6030fd --- /dev/null +++ b/01_helloWorld/helloWorld.spec.js @@ -0,0 +1,7 @@ +const helloWorld = require('./helloWorld'); + +describe('Hello World', function() { + test('says "Hello, World!"', function() { + expect(helloWorld()).toEqual('Hello, World!'); + }); +}); diff --git a/01_helloWorld/solution/helloWorld-solution.js b/01_helloWorld/solution/helloWorld-solution.js new file mode 100644 index 0000000..46569e0 --- /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..210a7f8 --- /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/README.md b/02_repeatString/README.md new file mode 100644 index 0000000..9c8123e --- /dev/null +++ b/02_repeatString/README.md @@ -0,0 +1,29 @@ +# Exercise 02 - repeatString + +Write a function that simply repeats the string a given number of times: + +```javascript +repeatString('hey', 3) // returns 'heyheyhey' +``` + +This function will take two arguments, `string` and `num`. + +*Note:* The exercises after this one will not have arguments provided as this one does - you will need to provide them yourself from now on. So read each exercise's README carefully to see what kinds of arguments will be expected. + +You will notice in this exercise that there are multiple tests (see in file `repeatString.spec.js`). Only the first test is currently enabled. So after making sure that this first one passes, enable the others one by one by deleting the `.skip` from the `test.skip()` function. + + +## Hints + +- Take note of the above function call- how exactly is it being called? + +- You're going to want to use a loop for this one. + +- Create a variable to hold the string you're going to return, create a loop that repeats the given number of times and add the given string to the result on each loop. + +- If running `npm test repeatString.spec.js` returns results similar to the below, make sure you have enabled the rest of the tests, as described in the instructions above. + +``` +Test Suites: 1 passed, 1 total +Tests: 6 skipped, 1 passed, 7 total +``` diff --git a/02_repeatString/repeatString.js b/02_repeatString/repeatString.js new file mode 100644 index 0000000..4359bbe --- /dev/null +++ b/02_repeatString/repeatString.js @@ -0,0 +1,6 @@ +const repeatString = function() { + +}; + +// Do not edit below this line +module.exports = repeatString; diff --git a/02_repeatString/repeatString.spec.js b/02_repeatString/repeatString.spec.js new file mode 100644 index 0000000..912ac20 --- /dev/null +++ b/02_repeatString/repeatString.spec.js @@ -0,0 +1,37 @@ +const repeatString = require('./repeatString') + +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 randomly generated. */ + expect(repeatString('hey', number).match(/((hey))/g).length).toEqual(number); + }); + test.skip('works with blank strings', () => { + expect(repeatString('', 10)).toEqual(''); + }); +}); diff --git a/02_repeatString/solution/repeatString-solution.js b/02_repeatString/solution/repeatString-solution.js new file mode 100644 index 0000000..67a765e --- /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..c506ce1 --- /dev/null +++ b/02_repeatString/solution/repeatString-solution.spec.js @@ -0,0 +1,39 @@ +const repeatString = require('./repeatString-solution'); + +describe('repeatString', () => { + test('repeats the string', () => { + expect(repeatString('hey', 3)).toEqual('heyheyhey'); + }); + test('repeats the string many times', () => { + expect(repeatString('hey', 10)).toEqual('heyheyheyheyheyheyheyheyheyhey'); + }); + test('repeats the string 1 times', () => { + expect(repeatString('hey', 1)).toEqual('hey'); + }); + test('repeats the string 0 times', () => { + expect(repeatString('hey', 0)).toEqual(''); + }); + test('returns ERROR with negative numbers', () => { + expect(repeatString('hey', -1)).toEqual('ERROR'); + }); + test('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('works with blank strings', () => { + expect(repeatString('', 10)).toEqual(''); + }); +}); diff --git a/03_reverseString/README.md b/03_reverseString/README.md new file mode 100644 index 0000000..036592f --- /dev/null +++ b/03_reverseString/README.md @@ -0,0 +1,13 @@ +# Exercise 03 - Reverse a String + +Pretty simple, write a function called `reverseString` that returns its input, reversed! + +```javascript +reverseString('hello there') // returns 'ereht olleh' +``` + +You will notice in this exercise that there are multiple tests (in the file `reverseString.spec.js`). Currently, only the first test is enabled. After ensuring that the first test passes, enable the remaining tests one by one by removing the `.skip` from the `test.skip()` function. + + +## Hints +Strings in JavaScript cannot be reversed directly so you're going to have to split it into something else first.. do the reversal and then join it back together into a string. diff --git a/03_reverseString/reverseString.js b/03_reverseString/reverseString.js new file mode 100644 index 0000000..f6790f0 --- /dev/null +++ b/03_reverseString/reverseString.js @@ -0,0 +1,6 @@ +const reverseString = function() { + +}; + +// Do not edit below this line +module.exports = reverseString; diff --git a/03_reverseString/reverseString.spec.js b/03_reverseString/reverseString.spec.js new file mode 100644 index 0000000..8adb887 --- /dev/null +++ b/03_reverseString/reverseString.spec.js @@ -0,0 +1,18 @@ +const reverseString = require('./reverseString') + +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/03_reverseString/solution/reverseString-solution.js b/03_reverseString/solution/reverseString-solution.js new file mode 100644 index 0000000..839f32e --- /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..629e071 --- /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('reverses multiple words', () => { + expect(reverseString('hello there')).toEqual('ereht olleh'); + }); + + test('works with numbers and punctuation', () => { + expect(reverseString('123! abc!')).toEqual('!cba !321'); + }); + test('works with blank strings', () => { + expect(reverseString('')).toEqual(''); + }); +}); diff --git a/04_removeFromArray/README.md b/04_removeFromArray/README.md new file mode 100644 index 0000000..d3a2ee9 --- /dev/null +++ b/04_removeFromArray/README.md @@ -0,0 +1,16 @@ +# Exercise 04 - removeFromArray + +Implement a function that takes an array and some other arguments then removes the other arguments from that array: + +```javascript +removeFromArray([1, 2, 3, 4], 3); // should remove 3 and return [1,2,4] +``` + +## Hints + +The first test on this one is fairly easy, but there are a few things to think about(or google) here for the later tests: + +- how to remove a single element from an array +- how to deal with multiple optional arguments in a javascript function +- [Check this link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments). Scroll down to the bit about `Array.from` or the spread operator. - [Or this link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters). + \ No newline at end of file diff --git a/04_removeFromArray/removeFromArray.js b/04_removeFromArray/removeFromArray.js new file mode 100644 index 0000000..1bedeb0 --- /dev/null +++ b/04_removeFromArray/removeFromArray.js @@ -0,0 +1,6 @@ +const removeFromArray = function() { + +}; + +// Do not edit below this line +module.exports = removeFromArray; diff --git a/04_removeFromArray/removeFromArray.spec.js b/04_removeFromArray/removeFromArray.spec.js new file mode 100644 index 0000000..21f34cf --- /dev/null +++ b/04_removeFromArray/removeFromArray.spec.js @@ -0,0 +1,25 @@ +const removeFromArray = require('./removeFromArray') + +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/04_removeFromArray/solution/removeFromArray-solution.js b/04_removeFromArray/solution/removeFromArray-solution.js new file mode 100644 index 0000000..cc2b13a --- /dev/null +++ b/04_removeFromArray/solution/removeFromArray-solution.js @@ -0,0 +1,28 @@ +// we have 2 solutions here, an easier one and a more advanced one. +// The easiest way to get an array of the rest 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 (array, ...args) { + // 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(array, ...args) { +// 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..ed03e08 --- /dev/null +++ b/04_removeFromArray/solution/removeFromArray-solution.spec.js @@ -0,0 +1,25 @@ +const removeFromArray = require('./removeFromArray-solution'); + +describe('removeFromArray', () => { + test('removes a single value', () => { + expect(removeFromArray([1, 2, 3, 4], 3)).toEqual([1, 2, 4]); + }); + test('removes multiple values', () => { + expect(removeFromArray([1, 2, 3, 4], 3, 2)).toEqual([1, 4]); + }); + test('ignores non present values', () => { + expect(removeFromArray([1, 2, 3, 4], 7, 'tacos')).toEqual([1, 2, 3, 4]); + }); + test('ignores non present values, but still works', () => { + expect(removeFromArray([1, 2, 3, 4], 7, 2)).toEqual([1, 3, 4]); + }); + test('can remove all values', () => { + expect(removeFromArray([1, 2, 3, 4], 1, 2, 3, 4)).toEqual([]); + }); + test('works with strings', () => { + expect(removeFromArray(['hey', 2, 3, 'ho'], 'hey', 3)).toEqual([2, 'ho']); + }); + test('only removes same type', () => { + expect(removeFromArray([1, 2, 3], '1', 3)).toEqual([1, 2]); + }); +}); diff --git a/05_sumAll/README.md b/05_sumAll/README.md new file mode 100644 index 0000000..8e18b9e --- /dev/null +++ b/05_sumAll/README.md @@ -0,0 +1,17 @@ +# Exercise 05 - sumAll + +Implement a function that takes 2 integers and returns the sum of every number between(and including) them: + +```javascript +sumAll(1, 4) // returns the sum of 1 + 2 + 3 + 4 which is 10 +``` + + +## Hints + +Think about how you would do this on pen and paper and then how you might translate that process into code: +- make sure you pay attention to the function parameters +- create a variable to hold the final sum +- loop through the given numbers ([link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Loops_and_iteration)) +- on each iteration add the number to the sum +- return the sum after finishing the loop diff --git a/05_sumAll/solution/sumAll-solution.js b/05_sumAll/solution/sumAll-solution.js new file mode 100644 index 0000000..ae01a5b --- /dev/null +++ b/05_sumAll/solution/sumAll-solution.js @@ -0,0 +1,21 @@ +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; + } + + // An alternative way to swap the values of min and max like above is to use the array destructuring syntax. + // Here's an optional article on it: https://www.freecodecamp.org/news/array-destructuring-in-es6-30e398f21d10/ + // if (min > max) [min, max] = [max, min]; + + let sum = 0; + for (let i = min; i <= max; 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..c78ae4e --- /dev/null +++ b/05_sumAll/solution/sumAll-solution.spec.js @@ -0,0 +1,25 @@ +const sumAll = require('./sumAll-solution'); + +describe('sumAll', () => { + test('sums numbers within the range', () => { + expect(sumAll(1, 4)).toEqual(10); + }); + test('works with large numbers', () => { + expect(sumAll(1, 4000)).toEqual(8002000); + }); + test('works with larger number first', () => { + expect(sumAll(123, 1)).toEqual(7626); + }); + test('returns ERROR with negative numbers', () => { + expect(sumAll(-10, 4)).toEqual('ERROR'); + }); + test('returns ERROR with non-integer parameters', () => { + expect(sumAll(2.5, 4)).toEqual('ERROR'); + }); + test('returns ERROR with non-number parameters', () => { + expect(sumAll(10, '90')).toEqual('ERROR'); + }); + test('returns ERROR with non-number parameters', () => { + expect(sumAll(10, [90, 1])).toEqual('ERROR'); + }); +}); diff --git a/05_sumAll/sumAll.js b/05_sumAll/sumAll.js new file mode 100644 index 0000000..00880c7 --- /dev/null +++ b/05_sumAll/sumAll.js @@ -0,0 +1,6 @@ +const sumAll = function() { + +}; + +// Do not edit below this line +module.exports = sumAll; diff --git a/05_sumAll/sumAll.spec.js b/05_sumAll/sumAll.spec.js new file mode 100644 index 0000000..1a9fb7c --- /dev/null +++ b/05_sumAll/sumAll.spec.js @@ -0,0 +1,22 @@ +const sumAll = require('./sumAll') + +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/README.md b/06_leapYears/README.md new file mode 100644 index 0000000..c4134da --- /dev/null +++ b/06_leapYears/README.md @@ -0,0 +1,16 @@ +# Exercise 06 - leapYears + +Create a function that determines whether or not a given year is a leap year. Leap years are determined by the following rules: + +> Leap years are years divisible by four (like 1984 and 2004). However, years divisible by 100 are not leap years (such as 1800 and 1900) unless they are divisible by 400 (like 1600 and 2000, which were in fact leap years). (Yes, it's all pretty confusing) +> +> -- [Learn to Program](https://pine.fm/LearnToProgram/chap_06.html) by Chris Pine + +```javascript +leapYears(2000) // is a leap year: returns true +leapYears(1985) // is not a leap year: returns false +``` + + +## Hints +- use an `if` statement and `&&` to make sure all the conditions are met properly diff --git a/06_leapYears/leapYears.js b/06_leapYears/leapYears.js new file mode 100644 index 0000000..681eeef --- /dev/null +++ b/06_leapYears/leapYears.js @@ -0,0 +1,6 @@ +const leapYears = function() { + +}; + +// Do not edit below this line +module.exports = leapYears; diff --git a/06_leapYears/leapYears.spec.js b/06_leapYears/leapYears.spec.js new file mode 100644 index 0000000..6fdaba9 --- /dev/null +++ b/06_leapYears/leapYears.spec.js @@ -0,0 +1,22 @@ +const leapYears = require('./leapYears') + +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/06_leapYears/solution/leapYears-solution.js b/06_leapYears/solution/leapYears-solution.js new file mode 100644 index 0000000..588bfd7 --- /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..19f639e --- /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('works with non century years', () => { + expect(leapYears(1997)).toBe(false); + }); + test('works with ridiculously futuristic non century years', () => { + expect(leapYears(34992)).toBe(true); + }); + test('works with century years', () => { + expect(leapYears(1900)).toBe(false); + }); + test('works with century years', () => { + expect(leapYears(1600)).toBe(true); + }); + test('works with century years', () => { + expect(leapYears(700)).toBe(false); + }); +}); diff --git a/07_tempConversion/README.md b/07_tempConversion/README.md new file mode 100644 index 0000000..77682f6 --- /dev/null +++ b/07_tempConversion/README.md @@ -0,0 +1,17 @@ +# Exercise 07 - tempConversion + +Write two functions that convert temperatures from Fahrenheit to Celsius, and vice versa: +``` +convertToCelsius(32) // fahrenheit to celsius, should return 0 + +convertToFahrenheit(0) // celsius to fahrenheit, should return 32 +``` + +Because we are human, we want the result temperature to be rounded to one decimal place: i.e., `convertToCelsius(100)` should return `37.8` and not `37.77777777777778`. + +This exercise asks you to create more than one function so the `module.exports` section of the spec file looks a little different this time. Nothing to worry about, we're just packaging both functions into a single object to be exported. + +## Hints +- You can find the relevant formulae on [Wikipedia](https://en.wikipedia.org/wiki/Conversion_of_units_of_temperature). + +- Try to find by yourself on the Internet how to round a number to 1 decimal place in JavaScript. If you struggle, have a look [here](https://stackoverflow.com/q/7342957/5433628). diff --git a/07_tempConversion/solution/tempConversion-solution.js b/07_tempConversion/solution/tempConversion-solution.js new file mode 100644 index 0000000..48883dc --- /dev/null +++ b/07_tempConversion/solution/tempConversion-solution.js @@ -0,0 +1,12 @@ +const convertToCelsius = function (fahrenheit) { + return Math.round((fahrenheit - 32) * (5 / 9) * 10) / 10; +}; + +const convertToFahrenheit = function (celsius) { + return Math.round(((celsius * 9) / 5 + 32) * 10) / 10; +}; + +module.exports = { + convertToCelsius, + convertToFahrenheit, +}; diff --git a/07_tempConversion/solution/tempConversion-solution.spec.js b/07_tempConversion/solution/tempConversion-solution.spec.js new file mode 100644 index 0000000..09b8faf --- /dev/null +++ b/07_tempConversion/solution/tempConversion-solution.spec.js @@ -0,0 +1,28 @@ +const { + convertToCelsius, + convertToFahrenheit, +} = require('./tempConversion-solution'); + +describe('convertToCelsius', () => { + test('works', () => { + expect(convertToCelsius(32)).toEqual(0); + }); + test('rounds to 1 decimal', () => { + expect(convertToCelsius(100)).toEqual(37.8); + }); + test('works with negatives', () => { + expect(convertToCelsius(-100)).toEqual(-73.3); + }); +}); + +describe('convertToFahrenheit', () => { + test('works', () => { + expect(convertToFahrenheit(0)).toEqual(32); + }); + test('rounds to 1 decimal', () => { + expect(convertToFahrenheit(73.2)).toEqual(163.8); + }); + test('works with negatives', () => { + expect(convertToFahrenheit(-10)).toEqual(14); + }); +}); diff --git a/07_tempConversion/tempConversion.js b/07_tempConversion/tempConversion.js new file mode 100644 index 0000000..14153e0 --- /dev/null +++ b/07_tempConversion/tempConversion.js @@ -0,0 +1,11 @@ +const convertToCelsius = function() { +}; + +const convertToFahrenheit = function() { +}; + +// Do not edit below this line +module.exports = { + convertToCelsius, + convertToFahrenheit +}; diff --git a/07_tempConversion/tempConversion.spec.js b/07_tempConversion/tempConversion.spec.js new file mode 100644 index 0000000..c4f9742 --- /dev/null +++ b/07_tempConversion/tempConversion.spec.js @@ -0,0 +1,25 @@ +const {convertToCelsius, convertToFahrenheit} = require('./tempConversion') + +describe('convertToCelsius', () => { + test('works', () => { + expect(convertToCelsius(32)).toEqual(0); + }); + test.skip('rounds to 1 decimal', () => { + expect(convertToCelsius(100)).toEqual(37.8); + }); + test.skip('works with negatives', () => { + expect(convertToCelsius(-100)).toEqual(-73.3); + }); +}); + +describe('convertToFahrenheit', () => { + test.skip('works', () => { + expect(convertToFahrenheit(0)).toEqual(32); + }); + test.skip('rounds to 1 decimal', () => { + expect(convertToFahrenheit(73.2)).toEqual(163.8); + }); + test.skip('works with negatives', () => { + expect(convertToFahrenheit(-10)).toEqual(14); + }); +}); diff --git a/README.md b/README.md new file mode 100644 index 0000000..f0b0250 --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +# JavaScript Exercises + +These JavaScript exercises are intended to complement the JavaScript content on The Odin Project (TOP). They should only be done when instructed during the course of the curriculum. + +**Note:** The `generator-exercise` file is not actually an exercise; it is a script that generates exercises. It was created to help efficiently write these exercises. + +## Contributing + +If you have a suggestion to improve an exercise, an idea for a new exercise, or notice an issue with an exercise, please feel free to open an issue after thoroughly reading our [contributing guide](https://github.com/TheOdinProject/.github/blob/main/CONTRIBUTING.md). + +## How To Use These Exercises + + +1. Fork and clone this repository. To learn how to fork a repository, see the GitHub documentation on how to [fork a repo](https://docs.github.com/en/get-started/quickstart/fork-a-repo). + - Copies of repositories on your machine are called clones. If you need help cloning to your local environment you can learn how from the GitHub documentation on [cloning a repository](https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/cloning-a-repository-from-github/cloning-a-repository). +2. Before you start working on any exercises, you should first ensure you have the following installed: + - **NPM**. You should have installed NPM already in our [Installing Node.js](https://www.theodinproject.com/paths/foundations/courses/foundations/lessons/installing-node-js) lesson. Just in case you need to check, type `npm --version` in your terminal. If you get back `Command 'npm' not found, but can be installed with:`, **do not follow the instructions in the terminal** to install with `apt-get` as this causes permission issues. Instead, go back to the installation lesson and install Node with NVM by following the instructions there. + - **Jest**. After cloning this repository to your local machine and installing NPM, go into the newly created directory (`cd javascript-exercises`) and run `npm install`. This will install Jest and set up the testing platform based on our preconfigured settings. (Note: if you get warnings that packages are out of date or contain vulnerabilities, you can safely ignore them for these exercises.) + +3. Each exercise includes the following: + + - A markdown file with a description of the task, an empty (or mostly empty) JavaScript file, and a set of tests. + - A `solutions` directory that contains a solution and the same test file with all of the tests unskipped. + + To complete an exercise, you'll need to go to the exercise directory with `cd exerciseName` in the terminal and run `npm test exerciseName.spec.js`. This should run the test file and show you the output. When you first run a test, it will fail. This is by design! You must open the exercise file and write the code needed to get the test to pass. +4. Some of the exercises have test conditions defined in their spec file as `test.skip` compared to `test`. This is purposeful. After you pass one `test`, you will change the next `test.skip` to `test` and test your code again. You'll do this until all conditions are satisfied. **All tests must pass at the same time**, and you should not have any `test.skip` instances by the time you finish an exercise. +5. Once you successfully finish an exercise, check the `solutions` directory within each exercise to compare it with yours. + - You should not be checking the solution for an exercise until you finish it! + - Keep in mind that TOP's solution is not the only solution. Generally as long as all of the tests pass, your solution should be fine. +6. Do not submit your solutions to this repo, as any PRs that do so will be closed without merging. + +**Note**: Due to the way Jest handles failed tests, it may return an exit code of 1 if any tests fail. NPM will interpret this as an error and you may see some `npm ERR!` messages after Jest runs. You can ignore these, or run your test with `npm test exerciseName.spec.js --silent` to supress the errors. + +The first exercise, `helloWorld`, will walk you through the process in-depth. + +## Debugging + +To debug functions, you can run the tests in the Visual Studio Code debugger terminal. You can open this by clicking the "Run and Debug" icon on the left or pressing Ctrl + Shift + D, then clicking JavaScript Debug Terminal. You will be able to set breakpoints as you would in the Chrome DevTools debugger. You can run `npm test exerciseName.spec.js` to then execute your code up until your breakpoint and step through your code as necessary. **NOTE**: To take advantage of the debugger, you **MUST** run the script in the debugger terminal, not the bash or zsh terminal.