diff --git a/index.html b/index.html
new file mode 100644
index 000000000..abb838a81
--- /dev/null
+++ b/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ LAB | JS Functions & Arrays
+
+
+
+
+
\ No newline at end of file
diff --git a/package.json b/package.json
new file mode 100644
index 000000000..7a6863d83
--- /dev/null
+++ b/package.json
@@ -0,0 +1,38 @@
+{
+ "name": "lab-javascript-functions-and-arrays",
+ "version": "1.0.0",
+ "license": "UNLICENSED",
+ "scripts": {
+ "test": "jest",
+ "test:watch": "jest --watchAll --verbose=false"
+ },
+ "devDependencies": {
+ "jest": "^26.6.3",
+ "jest-html-reporter": "^3.3.0",
+ "jest-junit": "^12.0.0"
+ },
+ "jest": {
+ "reporters": [
+ "default",
+ [
+ "./node_modules/jest-html-reporter",
+ {
+ "pageTitle": "Lab Solution",
+ "outputPath": "lab-solution.html",
+ "includeFailureMsg": true,
+ "includeConsoleLog": true
+ }
+ ]
+ ]
+ },
+ "jest-junit": {
+ "suiteNameTemplate": "{filepath}",
+ "classNameTemplate": "{classname}",
+ "titleTemplate": "{title}"
+ },
+ "prettier": {
+ "printWidth": 120,
+ "singleQuote": true,
+ "trailingComma": "none"
+ }
+ }
\ No newline at end of file
diff --git a/src/functions-and-arrays.js b/src/functions-and-arrays.js
index 3a7dbec41..66604a746 100644
--- a/src/functions-and-arrays.js
+++ b/src/functions-and-arrays.js
@@ -1,41 +1,89 @@
// Iteration #1: Find the maximum
-function maxOfTwoNumbers() {}
-
-
+function maxOfTwoNumbers(num1, num2) {
+ return Math.max(num1, num2);
+}
// Iteration #2: Find longest word
const words = ['mystery', 'brother', 'aviator', 'crocodile', 'pearl', 'orchard', 'crackpot'];
-function findLongestWord() {}
-
-
+function findLongestWord(words) {
+ if (words.length === 0) {
+ return null;
+ }
+ const lengths = words.map((word) => word.length);
+ const maxLength = Math.max(...lengths);
+ for (let i = 0; i < words.length; i++) {
+ if (words[i].length === maxLength) {
+ return words[i];
+ }
+ }
+}
// Iteration #3: Calculate the sum
const numbers = [6, 12, 1, 18, 13, 16, 2, 1, 8, 10];
-function sumNumbers() {}
-
-
+function sumNumbers(numbers) {
+ let currentSum = 0;
+ for (let i = 0; i < numbers.length; i++) {
+ currentSum += numbers[i];
+ }
+ return currentSum;
+}
// Iteration #3.1 Bonus:
-function sum() {}
-
+function getNumericValue(element) {
+ const type = typeof element;
+ if (type === 'number') {
+ return element;
+ } else if (type === 'string') {
+ return element.length;
+ } else if (element === true) {
+ return 1;
+ } else if (element === false) {
+ return 0;
+ } else {
+ throw new Error("Unsupported data type sir or ma'am");
+ }
+}
+function sum(mixedArray) {
+ const numbers = mixedArray.map(getNumericValue);
+ return sumNumbers(numbers);
+}
// Iteration #4: Calculate the average
// Level 1: Array of numbers
const numbersAvg = [2, 6, 9, 10, 7, 4, 1, 9];
-function averageNumbers() {}
+function averageNumbers(numbers) {
+ const n = numbers.length;
+ if (n === 0) {
+ return null;
+ }
+ const sum = sumNumbers(numbers);
+ return sum / n;
+}
// Level 2: Array of strings
const wordsArr = ['seat', 'correspond', 'linen', 'motif', 'hole', 'smell', 'smart', 'chaos', 'fuel', 'palace'];
-function averageWordLength() { }
+function averageWordLength(words) {
+ const lengths = words.map((word) => word.length);
+ const n = lengths.length;
+ if (n === 0) {
+ return null;
+ }
+
+ const sum = sumNumbers(lengths);
+ return sum / n;
+}
// Bonus - Iteration #4.1
-function avg() {}
+function avg(mixedArray) {
+ const numbers = mixedArray.map(getNumericValue);
+ return averageNumbers(numbers);
+}
// Iteration #5: Unique arrays
const wordsUnique = [
@@ -52,16 +100,30 @@ const wordsUnique = [
'bring'
];
-function uniquifyArray() {}
-
-
+function uniquifyArray(words) {
+ if (words.length === 0) {
+ return null;
+ }
+ const uniqueArray = [];
+ words.forEach((word) => {
+ const isRepeated = uniqueArray.some((previousWord) => previousWord === word);
+ if (!isRepeated) {
+ uniqueArray.push(word);
+ }
+ });
+ return uniqueArray;
+}
// Iteration #6: Find elements
const wordsFind = ['machine', 'subset', 'trouble', 'starting', 'matter', 'eating', 'truth', 'disobedience'];
-function doesWordExist() {}
-
-
+// Declare una función llamada doesWordExist que recibirá un array de palabras como un argumento, y una palabra a buscar como el otro. Devuelve true si existe, en caso contrario, devuelve false. No utilice indexOf para esta función.
+function doesWordExist(words, wordToFind) {
+ if (words.length === 0) {
+ return null;
+ }
+ return words.some((word) => word === wordToFind);
+}
// Iteration #7: Count repetition
const wordsCount = [
@@ -78,9 +140,9 @@ const wordsCount = [
'matter'
];
-function howManyTimes() {}
-
-
+function howManyTimes(words, wordToFind) {
+ return words.filter((word) => word === wordToFind).length;
+}
// Iteration #8: Bonus
const matrix = [
@@ -106,10 +168,100 @@ const matrix = [
[1, 70, 54, 71, 83, 51, 54, 69, 16, 92, 33, 48, 61, 43, 52, 1, 89, 19, 67, 48]
];
-function greatestProduct() {}
+const ADJACENT_NUMBERS = 4;
+function multiplyNums(nums) {
+ let currentProduct = 1;
+ for (let i = 0; i < nums.length; i++) {
+ currentProduct = currentProduct * nums[i];
+ }
+ return currentProduct;
+}
+function getProductsOfLines(matrix, lineType) {
+ // Get a list of lines, each one represented by a list of coordinates:
+ const sideLength = matrix.length;
+ const getLineIndex = {
+ horizontal: (row, col) => row,
+ vertical: (row, col) => col,
+ diagonal_ltr: (row, col) => row + col,
+ diagonal_rtl: (row, col) => sideLength + col - row - 1
+ };
+
+ const lines = [];
+ for (let row = 0; row < sideLength; row++) {
+ for (let col = 0; col < sideLength; col++) {
+ const lineIndex = getLineIndex[lineType](row, col);
+ lines[lineIndex] ??= [];
+ lines[lineIndex].push([row, col]);
+ }
+ }
+
+ // Get products of the lines:
+ const products = [];
+ const lineToProduct = (lineCoordinates) => {
+ const valuesInLine = lineCoordinates.map(([row, col]) => matrix[row][col]);
+ const product = multiplyNums(valuesInLine);
+ products.push(product);
+ };
+
+ lines.forEach((lineCoordinates) => {
+ const lineLength = lineCoordinates.length;
+
+ // If the line is short enough, we can just process it all (as in some diagonals):
+ if (lineLength <= ADJACENT_NUMBERS) {
+ lineToProduct(lineCoordinates);
+ return;
+ }
+
+ // If the line is longer than ADJACENT_NUMBERS, we need to calculate every chunk separately:
+ const lastSliceIndex = lineLength - ADJACENT_NUMBERS;
+ for (let sliceIndex = 0; sliceIndex <= lastSliceIndex; sliceIndex++) {
+ const sliceEndIndex = sliceIndex + ADJACENT_NUMBERS;
+ const sliceCoordinates = lineCoordinates.slice(sliceIndex, sliceEndIndex);
+ lineToProduct(sliceCoordinates);
+ }
+ });
+
+ return products;
+}
+
+function greatestProduct(matrix) {
+ const verticalProducts = getProductsOfLines(matrix, 'vertical');
+ const horizontProducts = getProductsOfLines(matrix, 'horizontal');
+
+ return Math.max(...verticalProducts, ...horizontProducts);
+}
+
+function greatestProductOfDiagonals(matrix) {
+ const diagonal1Products = getProductsOfLines(matrix, 'diagonal_ltr');
+ const diagonal2Products = getProductsOfLines(matrix, 'diagonal_rtl');
+
+ return Math.max(...diagonal1Products, ...diagonal2Products);
+}
+
+// Diagonal coordinates ltr:
+// [ [0, 0] ],
+// [ [1, 0], [0, 1] ],
+// [ [2, 0], [1, 1], [0, 2] ],
+// [ [3, 0], [2, 1], [1, 2], [0, 3] ],
+// [ [4, 0], [3, 1], [2, 2], [1, 3], [0, 4] ],
+// [ [4, 1], [3, 2], [2, 3], [1, 4] ],
+// [ [4, 2], [3, 3], [2, 4] ],
+// [ [4, 3], [3, 4] ],
+// [ [4, 4] ],
+
+// Diagonal coordinates rtl:
+// [ [0, 4] ],
+// [ [0, 3], [1, 4] ],
+// [ [0, 2], [1, 3], [2, 4] ],
+// [ [0, 1], [1, 2], [2, 3], [3, 4] ],
+// [ [0, 0], [1, 1], [2, 2], [3, 3], [4, 4] ],
+// [ [1, 0], [2, 1], [3, 2], [4, 3] ],
+// [ [2, 0], [3, 1], [4, 2] ],
+// [ [3, 0], [4, 1] ],
+// [ [4, 0] ],
// The following is required to make unit tests work.
/* Environment setup. Do not modify the below code. */
@@ -127,4 +279,4 @@ if (typeof module !== 'undefined') {
howManyTimes,
greatestProduct
};
-}
+}
\ No newline at end of file
diff --git a/tests/functions-and-arrays.spec.js b/tests/functions-and-arrays.spec.js
index 21ec1130c..ca7fd9f08 100644
--- a/tests/functions-and-arrays.spec.js
+++ b/tests/functions-and-arrays.spec.js
@@ -1,3 +1,17 @@
+const {
+ maxOfTwoNumbers,
+ findLongestWord,
+ sumNumbers,
+ sum,
+ averageNumbers,
+ averageWordLength,
+ avg,
+ uniquifyArray,
+ doesWordExist,
+ howManyTimes,
+ greatestProduct
+} = require('./../src/functions-and-arrays');
+
const shuffle = (currentArray) => {
const array = [...currentArray];
let counter = array.length;
@@ -12,47 +26,45 @@ const shuffle = (currentArray) => {
return array;
};
-
-
describe('Find the maximum', () => {
- it('should declare a function named maxOfTwoNumbers', () => {
+ test('should declare a function named maxOfTwoNumbers', () => {
expect(typeof maxOfTwoNumbers).toBe('function');
});
- it('should return greater of two arguments - if the first argument greater', () => {
+ test('should return greater of two arguments - if the first argument greater', () => {
expect(maxOfTwoNumbers(2, 1)).toBe(2);
expect(maxOfTwoNumbers(5, -7)).toBe(5);
});
- it('should return greater of two arguments - if the second argument greater', () => {
+ test('should return greater of two arguments - if the second argument greater', () => {
expect(maxOfTwoNumbers(1, 3)).toBe(3);
expect(maxOfTwoNumbers(-5, 3)).toBe(3);
});
- it('should return either arguments - if both arguments are equal', () => {
+ test('should return either arguments - if both arguments are equal', () => {
expect(maxOfTwoNumbers(4, 4)).toBe(4);
});
});
describe('Find the longest word', () => {
- it('should declare a function named findLongestWord', () => {
+ test('should declare a function named findLongestWord', () => {
expect(typeof findLongestWord).toBe('function');
});
- it('should return null when called with an empty array', () => {
+ test('should return null when called with an empty array', () => {
expect(findLongestWord([])).toBe(null);
});
- it('should return the word when called with a single-word array', () => {
+ test('should return the word when called with a single-word array', () => {
expect(findLongestWord(['foo'])).toBe('foo');
});
- it('should return the first occurrence of the word when longest have multiple occurrences ', () => {
+ test('should return the first occurrence of the word when longest have multiple occurrences ', () => {
expect(findLongestWord(['foo', 'bar'])).toBe('foo');
expect(findLongestWord(['bar', 'foo'])).toBe('bar');
});
- it('should return the longest occurrence when it has multiple words', () => {
+ test('should return the longest occurrence when it has multiple words', () => {
let words = ['a', 'zab', '12abc', '$$abcd', 'abcde', 'ironhack'];
for (let i = 0; i < 10; i++) {
words = shuffle(words);
@@ -62,106 +74,104 @@ describe('Find the longest word', () => {
});
describe('Calculate the sum of array of numbers', () => {
- it('should declare a function named sumNumbers', () => {
+ test('should declare a function named sumNumbers', () => {
expect(typeof sumNumbers).toBe('function');
});
- it('should return zero if receives an empty array when called', () => {
+ test('should return zero if receives an empty array when called', () => {
expect(sumNumbers([])).toBe(0);
});
- it('should return the sum with one number array', () => {
+ test('should return the sum with one number array', () => {
expect(sumNumbers([4])).toBe(4);
});
- it('should return zero if all elements are zero', () => {
+ test('should return zero if all elements are zero', () => {
expect(sumNumbers([0, 0, 0, 0, 0])).toBe(0);
});
- it('should return the sum when passed array of numbers', () => {
+ test('should return the sum when passed array of numbers', () => {
expect(sumNumbers([10, 5, 4, 32, 8])).toBe(59);
});
});
describe('Bonus: Calculate the sum', () => {
- it('should declare a function named sum', () => {
+ test('should declare a function named sum', () => {
expect(typeof sum).toBe('function');
});
- it('should return zero if receives an empty array when called', () => {
+ test('should return zero if receives an empty array when called', () => {
expect(sum([])).toBe(0);
});
- it('should return the sum with one number array', () => {
+ test('should return the sum with one number array', () => {
expect(sum([4])).toBe(4);
});
- it('should return zero if all elements are zero', () => {
+ test('should return zero if all elements are zero', () => {
expect(sum([0, 0, 0, 0, 0])).toBe(0);
});
- it('should return the sum when passed array of numbers', () => {
+ test('should return the sum when passed array of numbers', () => {
expect(sum([10, 5, 4, 32, 8])).toBe(59);
});
- it('should return the sum when passed array of strings', () => {
+ test('should return the sum when passed array of strings', () => {
expect(sum(['ana', 'marco', 'nicolas', 'tania', 'ptwd'])).toBe(24);
});
- it('should return the sum when passed array of mixed strings and numbers - ', () => {
+ test('should return the sum when passed array of mixed strings and numbers - ', () => {
expect(sum([6, 12, 'miami', 1, 'barca', '200', 'lisboa', 8, 10])).toBe(56);
});
-
- it('should return the sum when passed array of mixed strings, numbers and booleans - ', () => {
+ test('should return the sum when passed array of mixed strings, numbers and booleans - ', () => {
// false is counted as 0
expect(sum([6, 12, 'miami', 1, 'barca', '200', 'lisboa', 8, false])).toBe(46);
// true is counted as 1
expect(sum([6, 12, 'miami', 1, 'barca', '200', 'lisboa', 8, true])).toBe(47);
});
-
- it('should throw an error when unsupported data type (object or array) present in the array', () => {
- expect(() => sum([6, 12, 'miami', 1, 'barca', '200', 'lisboa', 8, [], {}])).toThrow();
+ test('should throw an error when unsupported data type (object or array) present in the array', () => {
+ expect(() => sum([6, 12, 'miami', 1, 'barca', '200', 'lisboa', 8, [], {}])).toThrow(
+ new Error("Unsupported data type sir or ma'am")
+ );
});
-
});
describe('Calculate the average of an array of numbers', () => {
- it('should declare a function named averageNumbers', () => {
+ test('should declare a function named averageNumbers', () => {
expect(typeof averageNumbers).toBe('function');
});
- it('should return null if receives an empty array when called', () => {
+ test('should return null if receives an empty array when called', () => {
expect(averageNumbers([])).toBe(null);
});
- it('should return the average of a one-element array', () => {
+ test('should return the average of a one-element array', () => {
expect(averageNumbers([9])).toBe(9);
});
- it('should return the average even with negative values', () => {
+ test('should return the average even with negative values', () => {
expect(averageNumbers([9, -3, -4, 6])).toBe(2);
});
- it('should return the average of the array', () => {
+ test('should return the average of the array', () => {
expect(averageNumbers([9, 10, 82, 92, 32, 102, 58])).toBe(55);
});
-
});
describe('Calculate the average of an array of strings', () => {
- it('should declare a function named averageWordLength', () => {
+ test('should declare a function named averageWordLength', () => {
expect(typeof averageWordLength).toBe('function');
});
- it('should return null if receives an empty array when called', () => {
+ test('should return null if receives an empty array when called', () => {
expect(averageWordLength([])).toBe(null);
});
- it('should return the average of a one-element array', () => {
+ test('should return the average of a one-element array', () => {
expect(averageWordLength(['ironhack'])).toBe(8);
});
- it('should return the average of a the array', () => {
+ test('should return the average of a the array', () => {
expect(
averageWordLength(['Ironhack', 'Madrid', 'Barcelona', 'Paris', 'Miami', 'Mexico', 'Berlin', 'Programmers'])
).toBe(7);
@@ -169,15 +179,15 @@ describe('Calculate the average of an array of strings', () => {
});
describe('Bonus: Calculate the average of a mixed elements array', () => {
- it('should declare a function named avg', () => {
+ test('should declare a function named avg', () => {
expect(typeof avg).toBe('function');
});
- it('should return null if receives an empty array when called', () => {
+ test('should return null if receives an empty array when called', () => {
expect(avg([])).toBe(null);
});
- it('should return the average of the array', () => {
+ test('should return the average of the array', () => {
// false is counted as 0
expect(avg([6, 12, 'miami', 1, 'barca', '200', 'lisboa', 8, false])).toBe(46/9);
// true is counted as 1
@@ -186,23 +196,23 @@ describe('Bonus: Calculate the average of a mixed elements array', () => {
});
describe('Unique array', () => {
- it('should declare a function named uniquifyArray', () => {
+ test('should declare a function named uniquifyArray', () => {
expect(typeof uniquifyArray).toBe('function');
});
- it('should return null if receives an empty array when called', () => {
+ test('should return null if receives an empty array when called', () => {
expect(uniquifyArray([])).toEqual(null);
});
- it('should return the correct uniqified array when an array of the same elements passed as argument', () => {
+ test('should return the correct uniqified array when an array of the same elements passed as argument', () => {
expect(uniquifyArray(['Ironhack', 'Ironhack', 'Ironhack'])).toEqual(['Ironhack']);
});
- it('should return the same array when no element is repeated', () => {
+ test('should return the same array when no element is repeated', () => {
expect(uniquifyArray(['Cat', 'Dog', 'Cow'])).toEqual(['Cat', 'Dog', 'Cow']);
});
- it('should return the uniquified array', () => {
+ test('should return the uniquified array', () => {
expect(
uniquifyArray(['iPhone', 'Samsung', 'Android', 'iOS', 'iPhone', 'Samsung', 'Nokia', 'Blackberry', 'Android'])
).toEqual(['iPhone', 'Samsung', 'Android', 'iOS', 'Nokia', 'Blackberry']);
@@ -210,45 +220,45 @@ describe('Unique array', () => {
});
describe('Find elements', () => {
- it('should declare a function named doesWordExist', () => {
+ test('should declare a function named doesWordExist', () => {
expect(typeof doesWordExist).toBe('function');
});
- it('should return null if receives an empty array when called', () => {
+ test('should return null if receives an empty array when called', () => {
expect(doesWordExist([])).toBe(null);
});
- it('should return true if the word we are looking for is the only one in the array', () => {
+ test('should return true if the word we are looking for is the only one in the array', () => {
expect(doesWordExist(['machine'], 'machine')).toBe(true);
});
- it('should return false if the word we are looking for is not in the array', () => {
+ test('should return false if the word we are looking for is not in the array', () => {
expect(doesWordExist(['machine', 'poison', 'eat', 'apple', 'horse'], 'ratatouille')).toBe(false);
});
- it('should return true if the word we are looking for is in the array', () => {
+ test('should return true if the word we are looking for is in the array', () => {
expect(doesWordExist(['pizza', 'sandwich', 'snack', 'soda', 'book', 'computer'], 'book')).toBe(true);
});
});
describe('Count repetition', () => {
- it('should declare a function named howManyTimes', () => {
+ test('should declare a function named howManyTimes', () => {
expect(typeof howManyTimes).toBe('function');
});
- it('should return 0 (zero) if receives an empty array when called', () => {
+ test('should return 0 (zero) if receives an empty array when called', () => {
expect(howManyTimes([])).toBe(0);
});
- it('should return 1 (one) when the word appears only one time in the array', () => {
+ test('should return 1 (one) when the word appears only one time in the array', () => {
expect(howManyTimes(['basketball', 'football', 'tennis'], 'tennis')).toBe(1);
});
- it("should return 0 (zero) when the word doesn't appear in the array", () => {
+ test("should return 0 (zero) when the word doesn't appear in the array", () => {
expect(howManyTimes(['basketball', 'football', 'tennis'], 'rugby')).toBe(0);
});
- it('should return 5 (five) when the word appears 5 times in the array', () => {
+ test('should return 5 (five) when the word appears 5 times in the array', () => {
expect(
howManyTimes(
[
@@ -271,11 +281,11 @@ describe('Count repetition', () => {
});
describe('Bonus Quest - greatestProduct', () => {
- it('should declare a function named greatestProduct', () => {
+ test('should declare a function named greatestProduct', () => {
expect(typeof greatestProduct).toBe('function');
});
- it('should return 1 (one) when all numbers of the arrays are 1', () => {
+ test('should return 1 (one) when all numbers of the arrays are 1', () => {
let matrix = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
@@ -301,7 +311,7 @@ describe('Bonus Quest - greatestProduct', () => {
expect(greatestProduct(matrix)).toBe(1);
});
- it('should return 16 when all the numbers of the arrays are 2', () => {
+ test('should return 16 when all the numbers of the arrays are 2', () => {
let matrix = [
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
@@ -326,4 +336,4 @@ describe('Bonus Quest - greatestProduct', () => {
];
expect(greatestProduct(matrix)).toBe(16);
});
-});
+});
\ No newline at end of file