diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 000000000..a85cb7eb8 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,15 @@ +{ + "arrowParens": "always", + "bracketSpacing": true, + "endOfLine": "lf", + "insertPragma": false, + "printWidth": 80, + "proseWrap": "preserve", + "quoteProps": "as-needed", + "requirePragma": false, + "semi": false, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "none", + "useTabs": false +} diff --git a/Ciphers/ROT13.js b/Ciphers/ROT13.js new file mode 100644 index 000000000..24eeacf8e --- /dev/null +++ b/Ciphers/ROT13.js @@ -0,0 +1,21 @@ +/** + * Transcipher a ROT13 cipher + * @param {String} text - string to be encrypted + * @return {String} - decrypted string + */ +const transcipher = (text) => { + const originalCharacterList = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' + const toBeMappedCharaterList = 'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm' + const index = x => originalCharacterList.indexOf(x) + const replace = x => index(x) > -1 ? toBeMappedCharaterList[index(x)] : x + return text.split('').map(replace).join('') +} + +(() => { + const messageToBeEncrypted = 'The quick brown fox jumps over the lazy dog' + console.log(`Original Text = "${messageToBeEncrypted}"`) + const rot13CipheredText = transcipher(messageToBeEncrypted) + console.log(`Ciphered Text = "${rot13CipheredText}"`) + const rot13DecipheredText = transcipher(rot13CipheredText) + console.log(`Deciphered Text = "${rot13DecipheredText}"`) +})() diff --git a/Conversions/HexToRGB.js b/Conversions/HexToRGB.js index f8f1662f5..5ee820b81 100644 --- a/Conversions/HexToRGB.js +++ b/Conversions/HexToRGB.js @@ -1,7 +1,7 @@ function hexStringToRGB (hexString) { - var r = (hexString.substring(1, 3)).toUpperCase() - var g = hexString.substring(3, 5).toUpperCase() - var b = hexString.substring(5, 7).toUpperCase() + var r = hexString.substring(0, 2) + var g = hexString.substring(2, 4) + var b = hexString.substring(4, 6) r = parseInt(r, 16) g = parseInt(g, 16) @@ -11,4 +11,4 @@ function hexStringToRGB (hexString) { return obj } -console.log(hexStringToRGB('javascript rock !!')) +console.log(hexStringToRGB('ffffff')) diff --git a/Conversions/RGBToHex.js b/Conversions/RGBToHex.js new file mode 100644 index 000000000..9fb15c6d3 --- /dev/null +++ b/Conversions/RGBToHex.js @@ -0,0 +1,16 @@ +function RGBToHex (r, g, b) { + if ( + typeof r !== 'number' || + typeof g !== 'number' || + typeof b !== 'number' + ) { + throw new TypeError('argument is not a Number') + } + + const toHex = n => (n || '0').toString(16).padStart(2, '0') + + return `#${toHex(r)}${toHex(g)}${toHex(b)}` +} + +console.log(RGBToHex(255, 255, 255) === '#ffffff') +console.log(RGBToHex(255, 99, 71) === '#ff6347') diff --git a/DIRECTORY.md b/DIRECTORY.md index 06e0a7d27..fa11e44dc 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -13,6 +13,7 @@ ## Ciphers * [CaesarsCipher](https://github.com/TheAlgorithms/Javascript/blob/master/Ciphers/CaesarsCipher.js) * [KeyFinder](https://github.com/TheAlgorithms/Javascript/blob/master/Ciphers/KeyFinder.js) + * [ROT13](https://github.com/TheAlgorithms/Javascript/blob/master/Ciphers/ROT13.js) * [VigenereCipher](https://github.com/TheAlgorithms/Javascript/blob/master/Ciphers/VigenereCipher.js) * [XORCipher](https://github.com/TheAlgorithms/Javascript/blob/master/Ciphers/XORCipher.js) @@ -22,6 +23,7 @@ * [DecimalToHex](https://github.com/TheAlgorithms/Javascript/blob/master/Conversions/DecimalToHex.js) * [DecimalToOctal](https://github.com/TheAlgorithms/Javascript/blob/master/Conversions/DecimalToOctal.js) * [HexToRGB](https://github.com/TheAlgorithms/Javascript/blob/master/Conversions/HexToRGB.js) + * [RGBToHex](https://github.com/TheAlgorithms/Javascript/blob/master/Conversions/RGBToHex.js) * [RomanToDecimal](https://github.com/TheAlgorithms/Javascript/blob/master/Conversions/RomanToDecimal.js) ## Data-Structures @@ -58,10 +60,12 @@ * [LevenshteinDistance](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/LevenshteinDistance.js) * [LongestCommonSubsequence](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/LongestCommonSubsequence.js) * [LongestIncreasingSubsequence](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/LongestIncreasingSubsequence.js) + * [LongestPalindromicSubsequence](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/LongestPalindromicSubsequence.js) * [MaxNonAdjacentSum](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/MaxNonAdjacentSum.js) * [MinimumCostPath](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/MinimumCostPath.js) * [NumberOfSubsetEqualToGivenSum](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/NumberOfSubsetEqualToGivenSum.js) * [SieveOfEratosthenes](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/SieveOfEratosthenes.js) + * [SudokuSolver](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/SudokuSolver.js) * [ZeroOneKnapsack](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/ZeroOneKnapsack.js) ## Graphs @@ -71,6 +75,7 @@ * [Dijkstra](https://github.com/TheAlgorithms/Javascript/blob/master/Graphs/Dijkstra.js) * [DijkstraSmallestPath](https://github.com/TheAlgorithms/Javascript/blob/master/Graphs/DijkstraSmallestPath.js) * [KruskalMST](https://github.com/TheAlgorithms/Javascript/blob/master/Graphs/KruskalMST.js) + * [NumberOfIslands](https://github.com/TheAlgorithms/Javascript/blob/master/Graphs/NumberOfIslands.js) * [PrimMST](https://github.com/TheAlgorithms/Javascript/blob/master/Graphs/PrimMST.js) ## Hashes @@ -85,30 +90,71 @@ ## Maths * [Abs](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/Abs.js) + * [Area](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/Area.js) + * [ArmstrongNumber](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/ArmstrongNumber.js) * [AverageMean](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/AverageMean.js) - * [digitSum](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/digitSum.js) + * [DigitSum](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/DigitSum.js) * [Factorial](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/Factorial.js) + * [Factors](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/Factors.js) * [Fibonacci](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/Fibonacci.js) * [FindHcf](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/FindHcf.js) * [FindLcm](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/FindLcm.js) * [GridGet](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/GridGet.js) * [isDivisible](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/isDivisible.js) + * [isOdd](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/isOdd.js) + * [MatrixMultiplication](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/MatrixMultiplication.js) * [MeanSquareError](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/MeanSquareError.js) * [ModularBinaryExponentiationRecursive](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/ModularBinaryExponentiationRecursive.js) + * [NumberOfDigits](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/NumberOfDigits.js) * [Palindrome](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/Palindrome.js) * [PascalTriangle](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/PascalTriangle.js) + * [PerfectCube](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/PerfectCube.js) + * [PerfectNumber](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/PerfectNumber.js) + * [PerfectSquare](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/PerfectSquare.js) * [PiApproximationMonteCarlo](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/PiApproximationMonteCarlo.js) * [Polynomial](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/Polynomial.js) * [PrimeCheck](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/PrimeCheck.js) * [ReversePolishNotation](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/ReversePolishNotation.js) * [SieveOfEratosthenes](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/SieveOfEratosthenes.js) + * test + * [Abs](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/Abs.test.js) + * [Area](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/Area.test.js) + * [ArmstrongNumber](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/ArmstrongNumber.test.js) + * [AverageMean](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/AverageMean.test.js) + * [DigitSum](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/DigitSum.test.js) + * [Factorial](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/Factorial.test.js) + * [Factors](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/Factors.test.js) + * [Fibonacci](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/Fibonacci.test.js) + * [FindHcf](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/FindHcf.test.js) + * [FindLcm](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/FindLcm.test.js) + * [GridGet](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/GridGet.test.js) + * [MeanSquareError](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/MeanSquareError.test.js) + * [ModularBinaryExponentiationRecursive](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/ModularBinaryExponentiationRecursive.test.js) + * [NumberOfDigits](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/NumberOfDigits.test.js) + * [Palindrome](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/Palindrome.test.js) + * [PascalTriangle](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/PascalTriangle.test.js) + * [PerfectCube](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/PerfectCube.test.js) + * [PerfectNumber](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/PerfectNumber.test.js) + * [PerfectSquare](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/PerfectSquare.test.js) + * [PiApproximationMonteCarlo](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/PiApproximationMonteCarlo.test.js) + * [Polynomial](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/Polynomial.test.js) + * [PrimeCheck](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/PrimeCheck.test.js) + * [ReversePolishNotation](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/ReversePolishNotation.test.js) + * [SieveOfEratosthenes](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/SieveOfEratosthenes.test.js) ## Project-Euler * [Problem1](https://github.com/TheAlgorithms/Javascript/blob/master/Project-Euler/Problem1.js) + * [Problem2](https://github.com/TheAlgorithms/Javascript/blob/master/Project-Euler/Problem2.js) + * [Problem3](https://github.com/TheAlgorithms/Javascript/blob/master/Project-Euler/Problem3.js) + * [Problem6](https://github.com/TheAlgorithms/Javascript/blob/master/Project-Euler/Problem6.js) + * [Problem7](https://github.com/TheAlgorithms/Javascript/blob/master/Project-Euler/Problem7.js) ## Recursive + * [BinarySearch](https://github.com/TheAlgorithms/Javascript/blob/master/Recursive/BinarySearch.js) * [EucledianGCD](https://github.com/TheAlgorithms/Javascript/blob/master/Recursive/EucledianGCD.js) + * [factorial](https://github.com/TheAlgorithms/Javascript/blob/master/Recursive/factorial.js) * [FibonacciNumberRecursive](https://github.com/TheAlgorithms/Javascript/blob/master/Recursive/FibonacciNumberRecursive.js) + * [Palindrome](https://github.com/TheAlgorithms/Javascript/blob/master/Recursive/Palindrome.js) * [TowerOfHanoi](https://github.com/TheAlgorithms/Javascript/blob/master/Recursive/TowerOfHanoi.js) ## Search @@ -121,6 +167,7 @@ * [StringSearch](https://github.com/TheAlgorithms/Javascript/blob/master/Search/StringSearch.js) ## Sorts + * [BeadSort](https://github.com/TheAlgorithms/Javascript/blob/master/Sorts/BeadSort.js) * [BogoSort](https://github.com/TheAlgorithms/Javascript/blob/master/Sorts/BogoSort.js) * [BubbleSort](https://github.com/TheAlgorithms/Javascript/blob/master/Sorts/BubbleSort.js) * [BucketSort](https://github.com/TheAlgorithms/Javascript/blob/master/Sorts/BucketSort.js) @@ -146,25 +193,43 @@ ## String * [CheckAnagram](https://github.com/TheAlgorithms/Javascript/blob/master/String/CheckAnagram.js) - * [CheckAnagram](https://github.com/TheAlgorithms/Javascript/blob/master/String/CheckAnagram.test.js) * [CheckPalindrome](https://github.com/TheAlgorithms/Javascript/blob/master/String/CheckPalindrome.js) - * [CheckPalindrome](https://github.com/TheAlgorithms/Javascript/blob/master/String/CheckPalindrome.test.js) + * [CheckPangram](https://github.com/TheAlgorithms/Javascript/blob/master/String/CheckPangram.js) * [CheckRearrangePalindrome](https://github.com/TheAlgorithms/Javascript/blob/master/String/CheckRearrangePalindrome.js) + * [CheckVowels](https://github.com/TheAlgorithms/Javascript/blob/master/String/CheckVowels.js) + * [CheckVowels](https://github.com/TheAlgorithms/Javascript/blob/master/String/CheckVowels.test.js) * [CheckWordOccurrence](https://github.com/TheAlgorithms/Javascript/blob/master/String/CheckWordOccurrence.js) * [CheckWordOcurrence](https://github.com/TheAlgorithms/Javascript/blob/master/String/CheckWordOcurrence.test.js) + * [createPurmutations](https://github.com/TheAlgorithms/Javascript/blob/master/String/createPurmutations.js) + * [FormatPhoneNumber](https://github.com/TheAlgorithms/Javascript/blob/master/String/FormatPhoneNumber.js) + * [FormatPhoneNumber](https://github.com/TheAlgorithms/Javascript/blob/master/String/FormatPhoneNumber.test.js) + * [GenerateGUID](https://github.com/TheAlgorithms/Javascript/blob/master/String/GenerateGUID.js) * [LevenshteinDistance](https://github.com/TheAlgorithms/Javascript/blob/master/String/LevenshteinDistance.js) * [LevenshteinDistance](https://github.com/TheAlgorithms/Javascript/blob/master/String/LevenshteinDistance.test.js) + * [MaxCharacter](https://github.com/TheAlgorithms/Javascript/blob/master/String/MaxCharacter.js) + * [MaxCharacter](https://github.com/TheAlgorithms/Javascript/blob/master/String/MaxCharacter.test.js) * [PatternMatching](https://github.com/TheAlgorithms/Javascript/blob/master/String/PatternMatching.js) - * [PatternMatching](https://github.com/TheAlgorithms/Javascript/blob/master/String/PatternMatching.test.js) + * [PermutateString](https://github.com/TheAlgorithms/Javascript/blob/master/String/PermutateString.js) + * [PermutateString](https://github.com/TheAlgorithms/Javascript/blob/master/String/PermutateString.test.js) * [ReverseString](https://github.com/TheAlgorithms/Javascript/blob/master/String/ReverseString.js) - * [ReverseString](https://github.com/TheAlgorithms/Javascript/blob/master/String/ReverseString.test.js) * [ReverseWords](https://github.com/TheAlgorithms/Javascript/blob/master/String/ReverseWords.js) - * [ReverseWords](https://github.com/TheAlgorithms/Javascript/blob/master/String/ReverseWords.test.js) + * test + * [CheckAnagram](https://github.com/TheAlgorithms/Javascript/blob/master/String/test/CheckAnagram.test.js) + * [CheckPalindrome](https://github.com/TheAlgorithms/Javascript/blob/master/String/test/CheckPalindrome.test.js) + * [CheckPangram](https://github.com/TheAlgorithms/Javascript/blob/master/String/test/CheckPangram.test.js) + * [PatternMatching](https://github.com/TheAlgorithms/Javascript/blob/master/String/test/PatternMatching.test.js) + * [ReverseString](https://github.com/TheAlgorithms/Javascript/blob/master/String/test/ReverseString.test.js) + * [ReverseWords](https://github.com/TheAlgorithms/Javascript/blob/master/String/test/ReverseWords.test.js) + * [ValidateEmail](https://github.com/TheAlgorithms/Javascript/blob/master/String/ValidateEmail.js) + * [ValidateEmail](https://github.com/TheAlgorithms/Javascript/blob/master/String/ValidateEmail.test.js) ## Timing-Functions + * [GetMonthDays](https://github.com/TheAlgorithms/Javascript/blob/master/Timing-Functions/GetMonthDays.js) + * [GetMonthDays](https://github.com/TheAlgorithms/Javascript/blob/master/Timing-Functions/GetMonthDays.test.js) * [IntervalTimer](https://github.com/TheAlgorithms/Javascript/blob/master/Timing-Functions/IntervalTimer.js) ## Trees + * [BreadthFirstTreeTraversal](https://github.com/TheAlgorithms/Javascript/blob/master/Trees/BreadthFirstTreeTraversal.js) * [DepthFirstSearch](https://github.com/TheAlgorithms/Javascript/blob/master/Trees/DepthFirstSearch.js) ## Web-Programming diff --git a/Dynamic-Programming/LongestPalindromicSubsequence.js b/Dynamic-Programming/LongestPalindromicSubsequence.js new file mode 100644 index 000000000..00c4b2a89 --- /dev/null +++ b/Dynamic-Programming/LongestPalindromicSubsequence.js @@ -0,0 +1,39 @@ +/* + LeetCode -> https://leetcode.com/problems/longest-palindromic-subsequence/ + + Given a string s, find the longest palindromic subsequence's length in s. + You may assume that the maximum length of s is 1000. + +*/ + +const longestPalindromeSubsequence = function (s) { + const n = s.length + + const dp = new Array(n).fill(0).map(item => new Array(n).fill(0).map(item => 0)) + + // fill predefined for single character + for (let i = 0; i < n; i++) { + dp[i][i] = 1 + } + + for (let i = 1; i < n; i++) { + for (let j = 0; j < n - i; j++) { + const col = j + i + if (s[j] === s[col]) { + dp[j][col] = 2 + dp[j + 1][col - 1] + } else { + dp[j][col] = Math.max(dp[j][col - 1], dp[j + 1][col]) + } + } + } + + return dp[0][n - 1] +} + +const main = () => { + console.log(longestPalindromeSubsequence('bbbab')) // 4 + console.log(longestPalindromeSubsequence('axbya')) // 3 + console.log(longestPalindromeSubsequence('racexyzcxar')) // 7 +} + +main() diff --git a/Dynamic-Programming/SudokuSolver.js b/Dynamic-Programming/SudokuSolver.js new file mode 100644 index 000000000..bbba70e7b --- /dev/null +++ b/Dynamic-Programming/SudokuSolver.js @@ -0,0 +1,50 @@ +const _board = [ + ['.', '9', '.', '.', '4', '2', '1', '3', '6'], + ['.', '.', '.', '9', '6', '.', '4', '8', '5'], + ['.', '.', '.', '5', '8', '1', '.', '.', '.'], + ['.', '.', '4', '.', '.', '.', '.', '.', '.'], + ['5', '1', '7', '2', '.', '.', '9', '.', '.'], + ['6', '.', '2', '.', '.', '.', '3', '7', '.'], + ['1', '.', '.', '8', '.', '4', '.', '2', '.'], + ['7', '.', '6', '.', '.', '.', '8', '1', '.'], + ['3', '.', '.', '.', '9', '.', '.', '.', '.'] +] + +const isValid = (board, row, col, k) => { + for (let i = 0; i < 9; i++) { + const m = 3 * Math.floor(row / 3) + Math.floor(i / 3) + const n = 3 * Math.floor(col / 3) + i % 3 + if (board[row][i] === k || board[i][col] === k || board[m][n] === k) { + return false + } + } + return true +} + +const sodokoSolver = (data) => { + for (let i = 0; i < 9; i++) { + for (let j = 0; j < 9; j++) { + if (data[i][j] === '.') { + for (let k = 1; k <= 9; k++) { + if (isValid(data, i, j, k)) { + data[i][j] = `${k}` + if (sodokoSolver(data)) { + return true + } else { + data[i][j] = '.' + } + } + } + return false + } + } + } + return true +} + +// testing +(() => { + if (sodokoSolver(_board)) { + console.log(_board) + } +})() diff --git a/Graphs/NumberOfIslands.js b/Graphs/NumberOfIslands.js new file mode 100644 index 000000000..1f8627fcd --- /dev/null +++ b/Graphs/NumberOfIslands.js @@ -0,0 +1,86 @@ +/* Number of Islands +https://dev.to/rattanakchea/amazons-interview-question-count-island-21h6 +Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water. + +two a dimensial grid map +each element is going to represent a peice of land +1 is land, +0 is water +output a number which is the number of islands + +Example 1: + Input: + 11110 + 11010 + 11000 + 00000 + + Output: 1 + +Example 2: + Input: + 11000 + 11000 + 00100 + 00011 + + Output: 3 + +I: two dimensional array +O: a single integer; total number of islands + +Pseudocode: + OUTER FUNCTION + set count to 0 + + INNER FUNCTION - flood (col, row) + if the tile is water + return + make tile water(flood tile) + invoke flood on the neighbor coordinates + + iterate over the matrix (col, row) + if the current element is a 1 + increment count + invoke flood (coordinates for col and row) + + Return the count +*/ +const grid = [ + ['1', '1', '0', '0', '0'], + ['1', '1', '0', '0', '0'], + ['0', '0', '1', '0', '0'], + ['0', '0', '0', '1', '1'] +] + +const islands = (matrixGrid) => { + const matrix = matrixGrid + let counter = 0 + + const flood = (row, col) => { + if (row < 0 || col < 0) return // Off the map above or left + if (row >= matrix.length || col >= matrix[row].length) return // Off the map below or right + + const tile = matrix[row][col] + if (tile !== '1') return + + matrix[row][col] = '0' + + flood(row + 1, col) // Down + flood(row - 1, col) // Up + flood(row, col + 1) // Right + flood(row, col - 1) // Left + } + + for (let row = 0; row < matrix.length; row += 1) { + for (let col = 0; col < matrix[row].length; col += 1) { + const current = matrix[row][col] + if (current === '1') { + flood(row, col) + counter += 1 + } + } + } + return counter +} +console.log(islands(grid)) diff --git a/Maths/Abs.js b/Maths/Abs.js index 454e4073a..4caa783ff 100644 --- a/Maths/Abs.js +++ b/Maths/Abs.js @@ -11,7 +11,7 @@ https://en.wikipedia.org/wiki/Absolute_value */ -function absVal (num) { +const absVal = (num) => { // Find absolute value of `num`. 'use strict' if (num < 0) { @@ -21,6 +21,4 @@ function absVal (num) { return num } -// Run `abs` function to find absolute value of two numbers. -console.log('The absolute value of -34 is ' + absVal(-34)) -console.log('The absolute value of 34 is ' + absVal(34)) +export { absVal } diff --git a/Maths/Area.js b/Maths/Area.js new file mode 100644 index 000000000..705de6a3e --- /dev/null +++ b/Maths/Area.js @@ -0,0 +1,99 @@ +/* + Calculate the area of various shapes + + Calculate the Surface Area of a Cube. + Example: surfaceAreaCube(1) will return 6 + More about: https://en.wikipedia.org/wiki/Area#Surface_area + */ +const surfaceAreaCube = (sideLength) => { + validateNumericParam(sideLength, 'sideLength') + return (6.0 * sideLength ** 2.0) +} + +/* + Calculate the Surface Area of a Sphere. + Wikipedia reference: https://en.wikipedia.org/wiki/Sphere + return 4 * pi * r^2 +*/ +const surfaceAreaSphere = (radius) => { + validateNumericParam(radius, 'radius') + return (4.0 * Math.PI * radius ** 2.0) +} + +/* + Calculate the area of a rectangle + Wikipedia reference: https://en.wikipedia.org/wiki/Area#Quadrilateral_area + return width * length +*/ +const areaRectangle = (length, width) => { + validateNumericParam(length, 'Length') + validateNumericParam(width, 'Width') + return (width * length) +} + +/* + Calculate the area of a square +*/ +const areaSquare = (sideLength) => { + validateNumericParam(sideLength, 'side length') + return (sideLength ** 2) +} + +/* + Calculate the area of a triangle + Wikipedia reference: https://en.wikipedia.org/wiki/Area#Triangle_area + return base * height / 2 +*/ +const areaTriangle = (base, height) => { + validateNumericParam(base, 'Base') + validateNumericParam(height, 'Height') + return (base * height) / 2.0 +} + +/* + Calculate the area of a parallelogram + Wikipedia reference: https://en.wikipedia.org/wiki/Area#Dissection,_parallelograms,_and_triangles +*/ +const areaParallelogram = (base, height) => { + validateNumericParam(base, 'Base') + validateNumericParam(height, 'Height') + return (base * height) +} + +/* + Calculate the area of a trapezium +*/ +const areaTrapezium = (base1, base2, height) => { + validateNumericParam(base1, 'Base One') + validateNumericParam(base2, 'Base Two') + validateNumericParam(height, 'Height') + return 1.0 / 2.0 * (base1 + base2) * height +} + +/* + Calculate the area of a circle +*/ +const areaCircle = (radius) => { + validateNumericParam(radius, 'Radius') + return (Math.PI * radius ** 2) +} + +/* + Calculate the area of a rhombus + Wikipedia reference: https://en.wikipedia.org/wiki/Rhombus +*/ +const areaRhombus = (diagonal1, diagonal2) => { + validateNumericParam(diagonal1, 'diagonal one') + validateNumericParam(diagonal2, 'diagonal two') + return (1 / 2 * diagonal1 * diagonal2) +} + +const validateNumericParam = (param, paramName = 'param') => { + if (typeof param !== 'number') { + throw new TypeError('The ' + paramName + ' should be type Number') + } else if (param < 0) { + throw new Error('The ' + paramName + ' only accepts non-negative values') + } +} + +export { surfaceAreaCube, surfaceAreaSphere, areaRectangle, areaSquare, areaTriangle, areaParallelogram, areaTrapezium, areaCircle, areaRhombus } diff --git a/Maths/ArmstrongNumber.js b/Maths/ArmstrongNumber.js new file mode 100644 index 000000000..71f448a7f --- /dev/null +++ b/Maths/ArmstrongNumber.js @@ -0,0 +1,24 @@ +/** + * Author: dephraiim + * License: GPL-3.0 or later + * + * An Armstrong number is equal to the sum of the cubes of its digits. + * For example, 370 is an Armstrong number because 3*3*3 + 7*7*7 + 0*0*0 = 370. + * An Armstrong number is often called Narcissistic number. + * + */ + +const armstrongNumber = (num) => { + if (num < 0 || typeof num !== 'number') return false + + let newSum = 0 + + const numArr = num.toString().split('') + numArr.forEach((num) => { + newSum += parseInt(num) ** numArr.length + }) + + return newSum === num +} + +export { armstrongNumber } diff --git a/Maths/AverageMean.js b/Maths/AverageMean.js index 28f96d53e..43f3f8ca0 100644 --- a/Maths/AverageMean.js +++ b/Maths/AverageMean.js @@ -14,8 +14,7 @@ const mean = (nums) => { // This is a function returns average/mean of array - var sum = 0 - var avg + let sum = 0 // This loop sums all values in the 'nums' array using forEach loop nums.forEach(function (current) { @@ -23,9 +22,8 @@ const mean = (nums) => { }) // Divide sum by the length of the 'nums' array. - avg = sum / nums.length + const avg = sum / nums.length return avg } -// Run `mean` Function to find average of a list of numbers. -console.log(mean([2, 4, 6, 8, 20, 50, 70])) +export { mean } diff --git a/Maths/digitSum.js b/Maths/DigitSum.js similarity index 70% rename from Maths/digitSum.js rename to Maths/DigitSum.js index 3f08cf807..792915d60 100644 --- a/Maths/digitSum.js +++ b/Maths/DigitSum.js @@ -1,18 +1,16 @@ // program to find sum of digits of a number // function which would calculate sum and return it -function digitSum (num) { +const digitSum = (num) => { // sum will store sum of digits of a number let sum = 0 // while will run untill num become 0 while (num) { - sum += (num % 10) + sum += num % 10 num = parseInt(num / 10) } return sum } -// assigning number -const num = 12345 -console.log(digitSum(num)) +export { digitSum } diff --git a/Maths/Factorial.js b/Maths/Factorial.js index c13878d90..04d9ef08c 100644 --- a/Maths/Factorial.js +++ b/Maths/Factorial.js @@ -13,10 +13,10 @@ 'use strict' -function calcRange (num) { +const calcRange = (num) => { // Generate a range of numbers from 1 to `num`. - var i = 1 - var range = [] + let i = 1 + const range = [] while (i <= num) { range.push(i) i += 1 @@ -24,9 +24,9 @@ function calcRange (num) { return range } -function calcFactorial (num) { - var factorial - var range = calcRange(num) +const calcFactorial = (num) => { + let factorial + const range = calcRange(num) // Check if the number is negative, positive, null, undefined, or zero if (num < 0) { @@ -43,11 +43,8 @@ function calcFactorial (num) { range.forEach(function (i) { factorial = factorial * i }) - return 'The factorial of ' + num + ' is ' + factorial + return `The factorial of ${num} is ${factorial}` } } -// Run `factorial` Function to find average of a list of numbers. - -var num = console.log('Enter a number: ') -console.log(calcFactorial(num)) +export { calcFactorial } diff --git a/Maths/Factors.js b/Maths/Factors.js new file mode 100644 index 000000000..68bbde6d2 --- /dev/null +++ b/Maths/Factors.js @@ -0,0 +1,16 @@ +/** + * Author: dephraiim + * License: GPL-3.0 or later + * + * More on Factors: + * https://www.mathsisfun.com/definitions/factor.html + * + */ + +const factorsOfANumber = (number = 0) => { + return Array.from(Array(number + 1).keys()).filter( + (num) => number % num === 0 + ) +} + +export { factorsOfANumber } diff --git a/Maths/Fibonacci.js b/Maths/Fibonacci.js index 9a4361781..3a8f83381 100644 --- a/Maths/Fibonacci.js +++ b/Maths/Fibonacci.js @@ -66,18 +66,10 @@ const FibonacciDpWithoutRecursion = (number) => { for (var i = 2; i < number; ++i) { table.push(table[i - 1] + table[i - 2]) } - return (table) + return table } -// testing - -console.log(FibonacciIterative(5)) -// Output: [ 1, 1, 2, 3, 5 ] -console.log(FibonacciRecursive(5)) -// Output: [ 1, 1, 2, 3, 5 ] - -console.log(FibonacciRecursiveDP(5)) -// Output: 5 - -console.log(FibonacciDpWithoutRecursion(5)) -// Output: [ 1, 1, 2, 3, 5 ] +export { FibonacciDpWithoutRecursion } +export { FibonacciIterative } +export { FibonacciRecursive } +export { FibonacciRecursiveDP } diff --git a/Maths/FindHcf.js b/Maths/FindHcf.js index f6b696219..19105b5aa 100644 --- a/Maths/FindHcf.js +++ b/Maths/FindHcf.js @@ -4,7 +4,7 @@ https://en.wikipedia.org/wiki/Greatest_common_divisor */ -function findHCF (x, y) { +const findHCF = (x, y) => { // If the input numbers are less than 1 return an error message. if (x < 1 || y < 1) { return 'Please enter values greater than zero.' @@ -27,4 +27,5 @@ function findHCF (x, y) { // When the while loop finishes the minimum of x and y is the HCF. return Math.min(x, y) } -console.log(findHCF(27, 36)) + +export { findHCF } diff --git a/Maths/FindLcm.js b/Maths/FindLcm.js index 60470e37e..0d09a7aff 100644 --- a/Maths/FindLcm.js +++ b/Maths/FindLcm.js @@ -12,9 +12,19 @@ 'use strict' // Find the LCM of two numbers. -function findLcm (num1, num2) { - var maxNum - var lcm +const findLcm = (num1, num2) => { + // If the input numbers are less than 1 return an error message. + if (num1 < 1 || num2 < 1) { + return 'Please enter values greater than zero.' + } + + // If the input numbers are not integers return an error message. + if (num1 !== Math.round(num1) || num2 !== Math.round(num2)) { + return 'Please enter whole numbers.' + } + + let maxNum + let lcm // Check to see whether num1 or num2 is larger. if (num1 > num2) { maxNum = num1 @@ -24,15 +34,10 @@ function findLcm (num1, num2) { lcm = maxNum while (true) { - if ((lcm % num1 === 0) && (lcm % num2 === 0)) { - break - } + if (lcm % num1 === 0 && lcm % num2 === 0) break lcm += maxNum } return lcm } -// Run `findLcm` Function -var num1 = 12 -var num2 = 76 -console.log(findLcm(num1, num2)) +export { findLcm } diff --git a/Maths/GridGet.js b/Maths/GridGet.js index 69ae502ef..44ae9a193 100644 --- a/Maths/GridGet.js +++ b/Maths/GridGet.js @@ -40,17 +40,14 @@ */ const gridGetX = (columns, index) => { - while ((index + 1) > columns) { + while (index + 1 > columns) { index = index - columns } - return (index + 1) + return index + 1 } const gridGetY = (columns, index) => { - return (Math.floor(index / columns)) + 1 + return Math.floor(index / columns) + 1 } -console.log(`If a square array has 400 elements, then the value of x for the 27th element is ${gridGetX(Math.sqrt(400), 27)}`) -console.log(`If an array has 7 columns and 3 rows, then the value of x for the 11th element is ${gridGetX(7, 11)}`) -console.log(`If a square array has 400 elements, then the value of y for the 27th element is ${gridGetY(Math.sqrt(400), 27)}`) -console.log(`If an array has 7 columns and 3 rows, then the value of y for the 11th element is ${gridGetY(7, 11)}`) +export { gridGetX, gridGetY } diff --git a/Maths/MatrixMultiplication.js b/Maths/MatrixMultiplication.js new file mode 100644 index 000000000..306c689f6 --- /dev/null +++ b/Maths/MatrixMultiplication.js @@ -0,0 +1,91 @@ +// Wikipedia URL for General Matrix Multiplication Concepts: https://en.wikipedia.org/wiki/Matrix_multiplication + +// This algorithm has multiple functions that ultimately check if the inputs are actually matrices and if two Matrices (that can be different sizes) can be multiplied together. +// matrices that are of the same size [2x2]x[2x2], and the second is the multiplication of two matrices that are not the same size [2x3]x[3x2]. + +// MatrixCheck tests to see if all of the rows of the matrix inputted have similar size columns +const matrixCheck = (matrix) => { + let columnNumb + for (let index = 0; index < matrix.length; index++) { + if (index === 0) { + columnNumb = matrix[index].length + } else if (matrix[index].length !== columnNumb) { + console.log('The columns in this array are not equal') + } else { + return columnNumb + } + } +} + +// tests to see if the matrices have a like side, i.e. the row length on the first matrix matches the column length on the second matrix, or vise versa. +const twoMatricesCheck = (first, second) => { + const [firstRowLength, secondRowLength, firstColLength, secondColLength] = [first.length, second.length, matrixCheck(first), matrixCheck(second)] + if (firstRowLength !== secondColLength || secondRowLength !== firstColLength) { + console.log('These matrices do not have a common side') + return false + } else { + return true + } +} + +// returns an empty array that has the same number of rows as the left matrix being multiplied. +// Uses Array.prototype.map() to loop over the first (or left) matrix and returns an empty array on each iteration. +const initiateEmptyArray = (first, second) => { + if (twoMatricesCheck(first, second)) { + const emptyArray = first.map(() => { + return [''] + }) + return emptyArray + } else { + return false + } +} + +// Finally, `matrixMult` uses `Array.prototype.push()`, multiple layers of nested `for` loops, the addition assignment `+=` operator and multiplication operator `*` to perform the dot product between two matrices of differing sizes. +// Dot product, takes the row of the first matrix and multiplies it by the column of the second matrix, the `twoMatricesCheck` tested to see if they were the same size already. +// The dot product for each iteration is then saved to its respective index into `multMatrix`. +const matrixMult = (firstArray, secondArray) => { + const multMatrix = initiateEmptyArray(firstArray, secondArray) + for (let rm = 0; rm < firstArray.length; rm++) { + const rowMult = [] + for (let col = 0; col < firstArray[0].length; col++) { + rowMult.push(firstArray[rm][col]) + } + for (let cm = 0; cm < firstArray.length; cm++) { + const colMult = [] + for (let row = 0; row < secondArray.length; row++) { + colMult.push(secondArray[row][cm]) + } + let newNumb = 0 + for (let index = 0; index < rowMult.length; index++) { + newNumb += rowMult[index] * colMult[index] + } + multMatrix[rm][cm] = newNumb + } + } + return multMatrix +} + +const firstMatrix = [ + [1, 2], + [3, 4] +] + +const secondMatrix = [ + [5, 6], + [7, 8] +] + +console.log(matrixMult(firstMatrix, secondMatrix)) // [ [ 19, 22 ], [ 43, 50 ] ] + +const thirdMatrix = [ + [-1, 4, 1], + [7, -6, 2] +] +const fourthMatrix = [ + [2, -2], + [5, 3], + [3, 2] +] + +console.log(matrixMult(thirdMatrix, fourthMatrix)) // [ [ 21, 16 ], [ -10, -28 ] ] diff --git a/Maths/MeanSquareError.js b/Maths/MeanSquareError.js index de9dcfd7f..edcd3e699 100644 --- a/Maths/MeanSquareError.js +++ b/Maths/MeanSquareError.js @@ -18,9 +18,4 @@ const meanSquaredError = (predicted, expected) => { return err / expected.length } -// testing -(() => { - console.log(meanSquaredError([1, 2, 3, 4], [1, 2, 3, 4]) === 0) - console.log(meanSquaredError([4, 3, 2, 1], [1, 2, 3, 4]) === 5) - console.log(meanSquaredError([2, 0, 2, 0], [0, 0, 0, 0]) === 3) -})() +export { meanSquaredError } diff --git a/Maths/ModularBinaryExponentiationRecursive.js b/Maths/ModularBinaryExponentiationRecursive.js index c30ed5f2a..b8374bd17 100644 --- a/Maths/ModularBinaryExponentiationRecursive.js +++ b/Maths/ModularBinaryExponentiationRecursive.js @@ -19,13 +19,4 @@ const modularBinaryExponentiation = (a, n, m) => { } } -const main = () => { - // binary_exponentiation(2, 10, 17) - // > 4 - console.log(modularBinaryExponentiation(2, 10, 17)) - // binary_exponentiation(3, 9, 12) - // > 3 - console.log(modularBinaryExponentiation(3, 9, 12)) -} - -main() +export { modularBinaryExponentiation } diff --git a/Maths/NumberOfDigits.js b/Maths/NumberOfDigits.js new file mode 100644 index 000000000..6414c65de --- /dev/null +++ b/Maths/NumberOfDigits.js @@ -0,0 +1,12 @@ +/** + * + * Author: dephraiim + * License: GPL-3.0 or later + * + * Returns the number of digits of a given integer + * + */ + +const numberOfDigit = (n) => Math.abs(n).toString().length + +export { numberOfDigit } diff --git a/Maths/Palindrome.js b/Maths/Palindrome.js index 4abc8d997..34804d34f 100644 --- a/Maths/Palindrome.js +++ b/Maths/Palindrome.js @@ -14,7 +14,7 @@ * @complexity: O(n) */ -function PalindromeRecursive (string) { +const PalindromeRecursive = (string) => { // Base case if (string.length < 2) return true @@ -26,7 +26,7 @@ function PalindromeRecursive (string) { return PalindromeRecursive(string.slice(1, string.length - 1)) } -function PalindromeIterative (string) { +const PalindromeIterative = (string) => { const _string = string .toLowerCase() .replace(/ /g, '') @@ -45,7 +45,4 @@ function PalindromeIterative (string) { return true } -// testing - -console.log(PalindromeRecursive('Javascript Community')) -console.log(PalindromeIterative('mom')) +export { PalindromeIterative, PalindromeRecursive } diff --git a/Maths/PascalTriangle.js b/Maths/PascalTriangle.js index eaf3f2a9e..868e36fca 100644 --- a/Maths/PascalTriangle.js +++ b/Maths/PascalTriangle.js @@ -1,6 +1,16 @@ -const numRows = 5 +const addRow = (triangle) => { + const previous = triangle[triangle.length - 1] + const newRow = [1] + for (let i = 0; i < previous.length - 1; i++) { + const current = previous[i] + const next = previous[i + 1] + newRow.push(current + next) + } + newRow.push(1) + return triangle.push(newRow) +} -var generate = function (numRows) { +const generate = (numRows) => { const triangle = [[1], [1, 1]] if (numRows === 0) { @@ -16,16 +26,5 @@ var generate = function (numRows) { } return triangle } -var addRow = function (triangle) { - const previous = triangle[triangle.length - 1] - const newRow = [1] - for (let i = 0; i < previous.length - 1; i++) { - const current = previous[i] - const next = previous[i + 1] - newRow.push(current + next) - } - newRow.push(1) - return triangle.push(newRow) -} -generate(numRows) +export { generate } diff --git a/Maths/PerfectCube.js b/Maths/PerfectCube.js new file mode 100644 index 000000000..bbfc821e2 --- /dev/null +++ b/Maths/PerfectCube.js @@ -0,0 +1,9 @@ +/** + * Author: dephraiim + * License: GPL-3.0 or later + * + */ + +const perfectCube = (num) => Math.round(num ** (1 / 3)) ** 3 === num + +export { perfectCube } diff --git a/Maths/PerfectNumber.js b/Maths/PerfectNumber.js new file mode 100644 index 000000000..ce8adefb6 --- /dev/null +++ b/Maths/PerfectNumber.js @@ -0,0 +1,30 @@ +/** + * Author: dephraiim + * License: GPL-3.0 or later + * + * == Perfect Number == + * In number theory, a perfect number is a positive integer that is equal to the sum of + * its positive divisors(factors), excluding the number itself. + * For example: 6 ==> divisors[1, 2, 3, 6] + * Excluding 6, the sum(divisors) is 1 + 2 + 3 = 6 + * So, 6 is a Perfect Number + * Other examples of Perfect Numbers: 28, 486, ... + * + * More on Perfect Number: + * https://en.wikipedia.org/wiki/Perfect_number + * + */ + +const factorsExcludingNumber = (n) => { + return [...Array(n).keys()].filter((num) => n % num === 0) +} + +const perfectNumber = (n) => { + const factorSum = factorsExcludingNumber(n).reduce((num, initialValue) => { + return num + initialValue + }, 0) + + return factorSum === n +} + +export { perfectNumber } diff --git a/Maths/PerfectSquare.js b/Maths/PerfectSquare.js new file mode 100644 index 000000000..d4909dbd4 --- /dev/null +++ b/Maths/PerfectSquare.js @@ -0,0 +1,9 @@ +/** + * Author: dephraiim + * License: GPL-3.0 or later + * + */ + +const perfectSquare = (num) => Math.sqrt(num) ** 2 === num + +export { perfectSquare } diff --git a/Maths/PiApproximationMonteCarlo.js b/Maths/PiApproximationMonteCarlo.js index a4b3d8b81..be7f754e4 100644 --- a/Maths/PiApproximationMonteCarlo.js +++ b/Maths/PiApproximationMonteCarlo.js @@ -1,7 +1,7 @@ // Wikipedia: https://en.wikipedia.org/wiki/Monte_Carlo_method // Video Explaination: https://www.youtube.com/watch?v=ELetCV_wX_c -function piEstimation (iterations = 100000) { +const piEstimation = (iterations = 100000) => { let circleCounter = 0 for (let i = 0; i < iterations; i++) { @@ -18,8 +18,4 @@ function piEstimation (iterations = 100000) { return pi } -function main () { - console.log(piEstimation()) -} - -main() +export { piEstimation } diff --git a/Maths/Polynomial.js b/Maths/Polynomial.js index 740ac3b25..41ec340ee 100644 --- a/Maths/Polynomial.js +++ b/Maths/Polynomial.js @@ -1,4 +1,3 @@ - /** * Polynomials are algebraic expressions consisting of two or more algebraic terms. * Terms of a polynomial are: @@ -20,18 +19,19 @@ class Polynomial { * Function to construct the polynomial in terms of x using the coefficientArray */ construct () { - this.polynomial = this.coefficientArray.map((coefficient, exponent) => { - if (coefficient === 0) { - return '0' - } - if (exponent === 0) { - return `(${coefficient})` - } else if (exponent === 1) { - return `(${coefficient}x)` - } else { - return `(${coefficient}x^${exponent})` - } - }) + this.polynomial = this.coefficientArray + .map((coefficient, exponent) => { + if (coefficient === 0) { + return '0' + } + if (exponent === 0) { + return `(${coefficient})` + } else if (exponent === 1) { + return `(${coefficient}x)` + } else { + return `(${coefficient}x^${exponent})` + } + }) .filter((x) => { if (x !== '0') { return x @@ -55,28 +55,9 @@ class Polynomial { */ evaluate (value) { return this.coefficientArray.reduce((result, coefficient, exponent) => { - return result + coefficient * (Math.pow(value, exponent)) + return result + coefficient * Math.pow(value, exponent) }, 0) } } -/** - * Function to perform tests - */ -const tests = () => { - const polynomialOne = new Polynomial([1, 2, 3, 4]) - console.log('Test 1: [1,2,3,4]') - console.log('Display Polynomial ', polynomialOne.display()) - // (4x^3) + (3x^2) + (2x) + (1) - console.log('Evaluate Polynomial value=2 ', polynomialOne.evaluate(2)) - // 49 - - const polynomialTwo = new Polynomial([5, 0, 0, -4, 3]) - console.log('Test 2: [5,0,0,-4,3]') - console.log('Display Polynomial ', polynomialTwo.display()) - // (3x^4) + (-4x^3) + (5) - console.log('Evaluate Polynomial value=1 ', polynomialTwo.evaluate(1)) - // 4 -} - -tests() +export { Polynomial } diff --git a/Maths/PrimeCheck.js b/Maths/PrimeCheck.js index d46dfab4f..c0f626ce6 100644 --- a/Maths/PrimeCheck.js +++ b/Maths/PrimeCheck.js @@ -9,6 +9,9 @@ const PrimeCheck = (n) => { // input: n: int // output: boolean + if (n === 1) return false + if (n === 0) return false + for (let i = 2; i * i <= n; i++) { if (n % i === 0) { return false @@ -17,13 +20,4 @@ const PrimeCheck = (n) => { return true } -const main = () => { - // PrimeCheck(1000003) - // > true - console.log(PrimeCheck(1000003)) - // PrimeCheck(1000001) - // > false - console.log(PrimeCheck(1000001)) -} - -main() +export { PrimeCheck } diff --git a/Maths/ReversePolishNotation.js b/Maths/ReversePolishNotation.js index ef31300a9..efe6240dc 100644 --- a/Maths/ReversePolishNotation.js +++ b/Maths/ReversePolishNotation.js @@ -1,6 +1,6 @@ // Wikipedia: https://en.wikipedia.org/wiki/Reverse_Polish_notation -function calcRPN (expression) { +const calcRPN = (expression) => { const operators = { '+': (a, b) => a + b, '-': (a, b) => a - b, @@ -12,7 +12,7 @@ function calcRPN (expression) { const stack = [] - tokens.forEach(token => { + tokens.forEach((token) => { const operator = operators[token] if (typeof operator === 'function') { @@ -30,6 +30,4 @@ function calcRPN (expression) { return stack.pop() } -console.log(calcRPN('2 2 2 * +') === 6) -console.log(calcRPN('2 2 + 2 *') === 8) -console.log(calcRPN('6 9 7 + 2 / + 3 *') === 42) +export { calcRPN } diff --git a/Maths/SieveOfEratosthenes.js b/Maths/SieveOfEratosthenes.js index 1e0a2e2b2..9393f58d8 100644 --- a/Maths/SieveOfEratosthenes.js +++ b/Maths/SieveOfEratosthenes.js @@ -1,9 +1,9 @@ -function sieveOfEratosthenes (n) { +const sieveOfEratosthenes = (n) => { /* - * Calculates prime numbers till a number n - * :param n: Number upto which to calculate primes - * :return: A boolean list contaning only primes - */ + * Calculates prime numbers till a number n + * :param n: Number upto which to calculate primes + * :return: A boolean list contaning only primes + */ const primes = new Array(n + 1) primes.fill(true) // set all as true initially primes[0] = primes[1] = false // Handling case for 0 and 1 @@ -18,14 +18,4 @@ function sieveOfEratosthenes (n) { return primes } -function main () { - const n = 69 // number till where we wish to find primes - const primes = sieveOfEratosthenes(n) - for (let i = 2; i <= n; i++) { - if (primes[i]) { - console.log(i) - } - } -} - -main() +export { sieveOfEratosthenes } diff --git a/Maths/isOdd.js b/Maths/isOdd.js new file mode 100644 index 000000000..fffe17930 --- /dev/null +++ b/Maths/isOdd.js @@ -0,0 +1,13 @@ +/* + * function to check if number is odd + * return true if number is odd + * else false + */ + +const isOdd = (value) => { + return !!((value & 1)) +} + +// testing +console.log(isOdd(2)) +console.log(isOdd(3)) diff --git a/Maths/test/Abs.test.js b/Maths/test/Abs.test.js new file mode 100644 index 000000000..116336f85 --- /dev/null +++ b/Maths/test/Abs.test.js @@ -0,0 +1,13 @@ +import { absVal } from '../Abs' + +describe('absVal', () => { + it('should return an absolute value of a negative number', () => { + const absOfNegativeNumber = absVal(-34) + expect(absOfNegativeNumber).toBe(34) + }) + + it('should return an absolute value of a positive number', () => { + const absOfPositiveNumber = absVal(50) + expect(absOfPositiveNumber).toBe(50) + }) +}) diff --git a/Maths/test/Area.test.js b/Maths/test/Area.test.js new file mode 100644 index 000000000..a7247a74b --- /dev/null +++ b/Maths/test/Area.test.js @@ -0,0 +1,99 @@ +import * as area from '../Area' + +describe('Testing surfaceAreaCube calculations', () => { + it('with natural number', () => { + const surfaceAreaOfOne = area.surfaceAreaCube(1.2) + const surfaceAreaOfThree = area.surfaceAreaCube(3) + expect(surfaceAreaOfOne).toBe(8.64) + expect(surfaceAreaOfThree).toBe(54) + }) + it('with negative argument, expect throw', () => { + expect(() => area.surfaceAreaCube(-1)).toThrow() + }) + it('with non-numeric argument, expect throw', () => { + expect(() => area.surfaceAreaCube('199')).toThrow() + }) +}) +describe('Testing surfaceAreaSphere calculations', () => { + it('with correct value', () => { + const calculateArea = area.surfaceAreaSphere(5) + const expected = 314.1592653589793 + expect(calculateArea).toBe(expected) + }) + it('with negative value, expect throw', () => { + expect(() => area.surfaceAreaSphere(-1)).toThrow() + }) +}) +describe('Testing areaRectangle calculations', () => { + it('with correct args', () => { + const areaRectangle = area.areaRectangle(2.5, 2) + expect(areaRectangle).toBe(5.0) + }) + it('with incorrect args, expect throw', () => { + expect(() => area.areaRectangle(-1, 20)).toThrow() + expect(() => area.areaRectangle('1', 0)).toThrow() + expect(() => area.areaRectangle(23, -1)).toThrow() + expect(() => area.areaRectangle(23, 'zero')).toThrow() + }) +}) +describe('Testing areaSquare calculations', () => { + it('with correct args', () => { + const areaSquare = area.areaSquare(2.5) + expect(areaSquare).toBe(6.25) + }) + it('with incorrect side length, expect throw', () => { + expect(() => area.areaSquare(-1)).toThrow() + expect(() => area.areaSquare('zero')).toThrow() + }) +}) +describe('Testing areaTriangle calculations', () => { + it('with correct args', () => { + const areaTriangle = area.areaTriangle(1.66, 3.44) + expect(areaTriangle).toBe(2.8552) + }) + it('with incorrect base and height, expect throw', () => { + expect(() => area.areaTriangle(-1, 1)).toThrow() + expect(() => area.areaTriangle(9, 'zero')).toThrow() + }) +}) +describe('Testing areaParallelogram calculations', () => { + it('with correct args', () => { + const areaParallelogram = area.areaParallelogram(1.66, 3.44) + expect(areaParallelogram).toBe(5.7104) + }) + it('with incorrect base and height, expect throw', () => { + expect(() => area.areaParallelogram(-1, 1)).toThrow() + expect(() => area.areaParallelogram(9, 'zero')).toThrow() + }) +}) +describe('Testing areaTrapezium calculations', () => { + it('with correct args', () => { + const areaTrapezium = area.areaTrapezium(1.66, 2.41, 4.1) + expect(areaTrapezium).toBe(8.3435) + }) + it('with incorrect bases and height, expect throw', () => { + expect(() => area.areaTrapezium(-1, 1, 0)).toThrow() + expect(() => area.areaTrapezium(9, 'zero', 2)).toThrow() + expect(() => area.areaTrapezium(9, 1, 'seven')).toThrow() + }) +}) +describe('Testing areaCircle calculations', () => { + it('with correct args', () => { + const areaCircle = area.areaCircle(3.456) + expect(areaCircle).toBe(37.52298159254666) + }) + it('with incorrect diagonal, expect throw', () => { + expect(() => area.areaCircle(-1)).toThrow() + expect(() => area.areaCircle('zero')).toThrow() + }) +}) +describe('Testing areaRhombus calculations', () => { + it('with correct args', () => { + const areaRhombus = area.areaRhombus(2.5, 2.0) + expect(areaRhombus).toBe(2.5) + }) + it('with incorrect diagonals, expect throw', () => { + expect(() => area.areaRhombus(7, -1)).toThrow() + expect(() => area.areaRhombus('zero', 2)).toThrow() + }) +}) diff --git a/Maths/test/ArmstrongNumber.test.js b/Maths/test/ArmstrongNumber.test.js new file mode 100644 index 000000000..01da1631d --- /dev/null +++ b/Maths/test/ArmstrongNumber.test.js @@ -0,0 +1,14 @@ +import { armstrongNumber } from '../ArmstrongNumber' + +describe('ArmstrongNumber', () => { + it('should return true for an armstrong number', () => { + expect(armstrongNumber(371)).toBeTruthy() + }) + + it('should return false for a non-armstrong number', () => { + expect(armstrongNumber(300)).toBeFalsy() + }) + it('should return false for negative values', () => { + expect(armstrongNumber(-2)).toBeFalsy() + }) +}) diff --git a/Maths/test/AverageMean.test.js b/Maths/test/AverageMean.test.js new file mode 100644 index 000000000..8b3d7bb13 --- /dev/null +++ b/Maths/test/AverageMean.test.js @@ -0,0 +1,11 @@ +import { mean } from '../AverageMean' + +describe('Tests for average mean', () => { + it('should be a function', () => { + expect(typeof mean).toEqual('function') + }) + it('should return the mean of an array of numbers', () => { + const meanFunction = mean([1, 2, 4, 5]) + expect(meanFunction).toBe(3) + }) +}) diff --git a/Maths/test/DigitSum.test.js b/Maths/test/DigitSum.test.js new file mode 100644 index 000000000..c9c828be5 --- /dev/null +++ b/Maths/test/DigitSum.test.js @@ -0,0 +1,11 @@ +import { digitSum } from '../DigitSum' + +describe('digitSum', () => { + it('is a function', () => { + expect(typeof digitSum).toEqual('function') + }) + it('should return the sum of digits of a given number', () => { + const sumOfNumber = digitSum(12345) + expect(sumOfNumber).toBe(15) + }) +}) diff --git a/Maths/test/Factorial.test.js b/Maths/test/Factorial.test.js new file mode 100644 index 000000000..bd22ad436 --- /dev/null +++ b/Maths/test/Factorial.test.js @@ -0,0 +1,35 @@ +import { calcFactorial } from '../Factorial' + +describe('calcFactorial', () => { + it('is a function', () => { + expect(typeof calcFactorial).toEqual('function') + }) + + it('should return a statement for value "0"', () => { + expect(calcFactorial(0)).toBe('The factorial of 0 is 1.') + }) + + it('should return a statement for "null" and "undefined"', () => { + const nullFactorial = calcFactorial(null) + const undefinedFactorial = calcFactorial(undefined) + + expect(nullFactorial).toBe( + 'Sorry, factorial does not exist for null or undefined numbers.' + ) + expect(undefinedFactorial).toBe( + 'Sorry, factorial does not exist for null or undefined numbers.' + ) + }) + + it('should not support negative numbers', () => { + const negativeFactorial = calcFactorial(-5) + expect(negativeFactorial).toBe( + 'Sorry, factorial does not exist for negative numbers.' + ) + }) + + it('should return the factorial of a positive number', () => { + const positiveFactorial = calcFactorial(3) + expect(positiveFactorial).toBe('The factorial of 3 is 6') + }) +}) diff --git a/Maths/test/Factors.test.js b/Maths/test/Factors.test.js new file mode 100644 index 000000000..1ad60132d --- /dev/null +++ b/Maths/test/Factors.test.js @@ -0,0 +1,10 @@ +import { factorsOfANumber } from '../Factors' + +describe('Factors', () => { + factorsOfANumber(50).forEach((num) => { + it(`${num} is a factor of 50`, () => { + const isFactor = 50 % num === 0 + expect(isFactor).toBeTruthy() + }) + }) +}) diff --git a/Maths/test/Fibonacci.test.js b/Maths/test/Fibonacci.test.js new file mode 100644 index 000000000..e5b9376f8 --- /dev/null +++ b/Maths/test/Fibonacci.test.js @@ -0,0 +1,30 @@ +import { + FibonacciDpWithoutRecursion, + FibonacciRecursiveDP, + FibonacciIterative, + FibonacciRecursive +} from '../Fibonacci' + +describe('Fibonanci', () => { + it('should return an array of numbers for FibonnaciIterative', () => { + expect(FibonacciIterative(5)).toEqual( + expect.arrayContaining([1, 1, 2, 3, 5]) + ) + }) + + it('should return an array of numbers for FibonnaciRecursive', () => { + expect(FibonacciRecursive(5)).toEqual( + expect.arrayContaining([1, 1, 2, 3, 5]) + ) + }) + + it('should return number for FibonnaciRecursiveDP', () => { + expect(FibonacciRecursiveDP(5)).toBe(5) + }) + + it('should return an array of numbers for FibonacciDpWithoutRecursion', () => { + expect(FibonacciDpWithoutRecursion(5)).toEqual( + expect.arrayContaining([1, 1, 2, 3, 5]) + ) + }) +}) diff --git a/Maths/test/FindHcf.test.js b/Maths/test/FindHcf.test.js new file mode 100644 index 000000000..ccb5c3045 --- /dev/null +++ b/Maths/test/FindHcf.test.js @@ -0,0 +1,20 @@ +import { findHCF } from '../FindHcf' + +describe('findHCF', () => { + it('should throw a statement for values less than 1', () => { + expect(findHCF(0, 0)).toBe('Please enter values greater than zero.') + }) + + it('should throw a statement for one value less than 1', () => { + expect(findHCF(0, 1)).toBe('Please enter values greater than zero.') + expect(findHCF(1, 0)).toBe('Please enter values greater than zero.') + }) + + it('should return an error for values non-integer values', () => { + expect(findHCF(2.24, 4.35)).toBe('Please enter whole numbers.') + }) + + it('should return the HCF of two given integers', () => { + expect(findHCF(27, 36)).toBe(9) + }) +}) diff --git a/Maths/test/FindLcm.test.js b/Maths/test/FindLcm.test.js new file mode 100644 index 000000000..1e5c0905c --- /dev/null +++ b/Maths/test/FindLcm.test.js @@ -0,0 +1,20 @@ +import { findLcm } from '../FindLcm' + +describe('findLcm', () => { + it('should throw a statement for values less than 1', () => { + expect(findLcm(0, 0)).toBe('Please enter values greater than zero.') + }) + + it('should throw a statement for one value less than 1', () => { + expect(findLcm(1, 0)).toBe('Please enter values greater than zero.') + expect(findLcm(0, 1)).toBe('Please enter values greater than zero.') + }) + + it('should return an error for values non-integer values', () => { + expect(findLcm(4.564, 7.39)).toBe('Please enter whole numbers.') + }) + + it('should return the LCM of two given integers', () => { + expect(findLcm(27, 36)).toBe(108) + }) +}) diff --git a/Maths/test/GridGet.test.js b/Maths/test/GridGet.test.js new file mode 100644 index 000000000..eef51fc6f --- /dev/null +++ b/Maths/test/GridGet.test.js @@ -0,0 +1,16 @@ +import { gridGetX, gridGetY } from '../GridGet' + +describe('GridGet', () => { + it('should have a value of x for the 27th element if the square array has 400 elements', () => { + expect(gridGetX(Math.sqrt(400), 27)).toEqual(8) + }) + it('should have a value of x for the 11th element if the square array has 7 columns and 3 rows', () => { + expect(gridGetX(7, 11)).toEqual(5) + }) + it('should have a value of y for the 27th element if the square array has 400 elements', () => { + expect(gridGetY(Math.sqrt(400), 27)).toEqual(2) + }) + it('should have a value of y for the 11th element if the square array has 7 columns and 3 rows ', () => { + expect(gridGetX(7, 11)).toEqual(5) + }) +}) diff --git a/Maths/test/MeanSquareError.test.js b/Maths/test/MeanSquareError.test.js new file mode 100644 index 000000000..ecd53de89 --- /dev/null +++ b/Maths/test/MeanSquareError.test.js @@ -0,0 +1,21 @@ +import { meanSquaredError } from '../MeanSquareError' + +describe('meanSquareError', () => { + it('should throw an error on non-array arguments', () => { + expect(() => meanSquaredError(1, 4)).toThrow('Argument must be an Array') + }) + + it('should throw an error on non equal length ', () => { + const firstArr = [1, 2, 3, 4, 5] + const secondArr = [1, 2, 3] + expect(() => meanSquaredError(firstArr, secondArr)).toThrow( + 'The two lists must be of equal length' + ) + }) + + it('should return the mean square error of two equal length arrays', () => { + const firstArr = [1, 2, 3, 4, 5] + const secondArr = [1, 3, 5, 6, 7] + expect(meanSquaredError(firstArr, secondArr)).toBe(2.6) + }) +}) diff --git a/Maths/test/ModularBinaryExponentiationRecursive.test.js b/Maths/test/ModularBinaryExponentiationRecursive.test.js new file mode 100644 index 000000000..9758d0ed1 --- /dev/null +++ b/Maths/test/ModularBinaryExponentiationRecursive.test.js @@ -0,0 +1,7 @@ +import { modularBinaryExponentiation } from '../ModularBinaryExponentiationRecursive' + +describe('modularBinaryExponentiation', () => { + it('should return the binary exponentiation', () => { + expect(modularBinaryExponentiation(2, 10, 17)).toBe(4) + }) +}) diff --git a/Maths/test/NumberOfDigits.test.js b/Maths/test/NumberOfDigits.test.js new file mode 100644 index 000000000..631e2cce3 --- /dev/null +++ b/Maths/test/NumberOfDigits.test.js @@ -0,0 +1,11 @@ +import { numberOfDigit } from '../NumberOfDigits' + +describe('NumberOfDigits', () => { + it('should return the correct number of digits for an integer', () => { + expect(numberOfDigit(1234000)).toBe(7) + }) + + it('should return the correct number of digits for a negative number', () => { + expect(numberOfDigit(-2346243)).toBe(7) + }) +}) diff --git a/Maths/test/Palindrome.test.js b/Maths/test/Palindrome.test.js new file mode 100644 index 000000000..53cb88395 --- /dev/null +++ b/Maths/test/Palindrome.test.js @@ -0,0 +1,16 @@ +import { PalindromeRecursive, PalindromeIterative } from '../Palindrome' + +describe('Palindrome', () => { + it('should return true for a palindrome for PalindromeRecursive', () => { + expect(PalindromeRecursive('mom')).toBeTruthy() + }) + it('should return true for a palindrome for PalindromeIterative', () => { + expect(PalindromeIterative('mom')).toBeTruthy() + }) + it('should return false for a non-palindrome for PalindromeRecursive', () => { + expect(PalindromeRecursive('Algorithms')).toBeFalsy() + }) + it('should return true for a non-palindrome for PalindromeIterative', () => { + expect(PalindromeIterative('JavaScript')).toBeFalsy() + }) +}) diff --git a/Maths/test/PascalTriangle.test.js b/Maths/test/PascalTriangle.test.js new file mode 100644 index 000000000..314d0f321 --- /dev/null +++ b/Maths/test/PascalTriangle.test.js @@ -0,0 +1,20 @@ +import { generate } from '../PascalTriangle' + +describe('Pascals Triangle', () => { + it('should have the the same length as the number', () => { + const pascalsTriangle = generate(5) + expect(pascalsTriangle.length).toEqual(5) + }) + it('should have same length as its index in the array', () => { + const pascalsTriangle = generate(5) + pascalsTriangle.forEach((arr, index) => { + expect(arr.length).toEqual(index + 1) + }) + }) + it('should return an array of arrays', () => { + const pascalsTriangle = generate(3) + expect(pascalsTriangle).toEqual( + expect.arrayContaining([[1], [1, 1], [1, 2, 1]]) + ) + }) +}) diff --git a/Maths/test/PerfectCube.test.js b/Maths/test/PerfectCube.test.js new file mode 100644 index 000000000..ff4b74f8f --- /dev/null +++ b/Maths/test/PerfectCube.test.js @@ -0,0 +1,10 @@ +import { perfectCube } from '../PerfectCube' + +describe('PerfectCube', () => { + it('should return true for a perfect cube', () => { + expect(perfectCube(125)).toBeTruthy() + }) + it('should return false for a non perfect cube', () => { + expect(perfectCube(100)).toBeFalsy() + }) +}) diff --git a/Maths/test/PerfectNumber.test.js b/Maths/test/PerfectNumber.test.js new file mode 100644 index 000000000..55b7d8426 --- /dev/null +++ b/Maths/test/PerfectNumber.test.js @@ -0,0 +1,10 @@ +import { perfectNumber } from '../PerfectNumber' + +describe('PerfectNumber', () => { + it('should return true for a perfect cube', () => { + expect(perfectNumber(28)).toBeTruthy() + }) + it('should return false for a non perfect cube', () => { + expect(perfectNumber(10)).toBeFalsy() + }) +}) diff --git a/Maths/test/PerfectSquare.test.js b/Maths/test/PerfectSquare.test.js new file mode 100644 index 000000000..86c8c3403 --- /dev/null +++ b/Maths/test/PerfectSquare.test.js @@ -0,0 +1,10 @@ +import { perfectSquare } from '../PerfectSquare' + +describe('PerfectSquare', () => { + it('should return true for a perfect cube', () => { + expect(perfectSquare(16)).toBeTruthy() + }) + it('should return false for a non perfect cube', () => { + expect(perfectSquare(10)).toBeFalsy() + }) +}) diff --git a/Maths/test/PiApproximationMonteCarlo.test.js b/Maths/test/PiApproximationMonteCarlo.test.js new file mode 100644 index 000000000..9727aa578 --- /dev/null +++ b/Maths/test/PiApproximationMonteCarlo.test.js @@ -0,0 +1,9 @@ +import { piEstimation } from '../PiApproximationMonteCarlo' + +describe('PiApproximationMonteCarlo', () => { + it('should be between the range of 2 to 4', () => { + const pi = piEstimation() + const piRange = pi >= 2 && pi <= 4 + expect(piRange).toBeTruthy() + }) +}) diff --git a/Maths/test/Polynomial.test.js b/Maths/test/Polynomial.test.js new file mode 100644 index 000000000..af5618ab3 --- /dev/null +++ b/Maths/test/Polynomial.test.js @@ -0,0 +1,37 @@ +import { Polynomial } from '../Polynomial' + +describe('Polynomial', () => { + it('should not return a expression for zero', () => { + const polynomial = new Polynomial([0]) + expect(polynomial.display()).toBe('') + }) + it('should not return an expression for zero values', () => { + const polynomial = new Polynomial([0, 0, 0, 0, 0]) + expect(polynomial.display()).toBe('') + }) + it('should return an expression for single a non zero value', () => { + const polynomial = new Polynomial([9]) + expect(polynomial.display()).toBe('(9)') + }) + it('should return an expression for two values', () => { + const polynomial = new Polynomial([3, 2]) + expect(polynomial.display()).toBe('(2x) + (3)') + }) + it('should return an expression for values including zero', () => { + const polynomial = new Polynomial([0, 2]) + expect(polynomial.display()).toBe('(2x)') + }) + it('should return an expression and evaluate it', () => { + const polynomial = new Polynomial([1, 2, 3, 4]) + expect(polynomial.display()).toBe('(4x^3) + (3x^2) + (2x) + (1)') + expect(polynomial.evaluate(2)).toEqual(49) + }) + it('should evaluate 0 for zero values', () => { + const polynomial = new Polynomial([0, 0, 0, 0]) + expect(polynomial.evaluate(5)).toEqual(0) + }) + it('should evaluate for negative values', () => { + const polynomial = new Polynomial([-1, -3, -4, -7]) + expect(polynomial.evaluate(-5)).toBe(789) + }) +}) diff --git a/Maths/test/PrimeCheck.test.js b/Maths/test/PrimeCheck.test.js new file mode 100644 index 000000000..da1cd1b52 --- /dev/null +++ b/Maths/test/PrimeCheck.test.js @@ -0,0 +1,14 @@ +import { PrimeCheck } from '../PrimeCheck' + +describe('PrimeCheck', () => { + it('should return true for Prime Numbers', () => { + expect(PrimeCheck(1000003)).toBeTruthy() + }) + it('should return false for Non Prime Numbers', () => { + expect(PrimeCheck(1000001)).toBeFalsy() + }) + it('should return false for 1 and 0', () => { + expect(PrimeCheck(1)).toBeFalsy() + expect(PrimeCheck(0)).toBeFalsy() + }) +}) diff --git a/Maths/test/ReversePolishNotation.test.js b/Maths/test/ReversePolishNotation.test.js new file mode 100644 index 000000000..8b880ee47 --- /dev/null +++ b/Maths/test/ReversePolishNotation.test.js @@ -0,0 +1,11 @@ +import { calcRPN } from '../ReversePolishNotation' + +describe('ReversePolishNotation', () => { + it('should evaluate correctly for two values', () => { + expect(calcRPN('2 3 +')).toEqual(5) + }) + it("should evaluate' for multiple values", () => { + expect(calcRPN('2 2 2 * +')).toEqual(6) + expect(calcRPN('6 9 7 + 2 / + 3 *')).toEqual(42) + }) +}) diff --git a/Maths/test/SieveOfEratosthenes.test.js b/Maths/test/SieveOfEratosthenes.test.js new file mode 100644 index 000000000..056693d39 --- /dev/null +++ b/Maths/test/SieveOfEratosthenes.test.js @@ -0,0 +1,14 @@ +import { sieveOfEratosthenes } from '../SieveOfEratosthenes' +import { PrimeCheck } from '../PrimeCheck' + +describe('should return an array of prime booleans', () => { + it('should have each element in the array as a prime boolean', () => { + const n = 30 + const primes = sieveOfEratosthenes(n) + primes.forEach((primeBool, index) => { + if (primeBool) { + expect(PrimeCheck(index)).toBeTruthy() + } + }) + }) +}) diff --git a/Project-Euler/Problem1.js b/Project-Euler/Problem1.js index 9c971942e..af3582f03 100644 --- a/Project-Euler/Problem1.js +++ b/Project-Euler/Problem1.js @@ -1,12 +1,15 @@ +// https://projecteuler.net/problem=1 /* Multiples of 3 and 5 If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. Find the sum of all the multiples of 3 or 5 below the provided parameter value number. */ -function multiplesThreeAndFive (num) { +const readline = require('readline') + +const multiplesThreeAndFive = (num) => { let total = 0 // total for calculating the sum - for (let i = 0; i <= num; i++) { + for (let i = 0; i < num; i++) { if (i % 3 === 0 || i % 5 === 0) { total += i } @@ -14,5 +17,11 @@ function multiplesThreeAndFive (num) { return total } -var num = console.log('Enter a number: ') -console.log(multiplesThreeAndFive(num)) // multiples3_5 function to calculate the sum of multiples of 3 and 5 within num +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout +}) +rl.question('Enter a number: ', function (num) { + console.log(multiplesThreeAndFive(num)) // multiples3_5 function to calculate the sum of multiples of 3 and 5 within num + rl.close() +}) diff --git a/Project-Euler/Problem2.js b/Project-Euler/Problem2.js index cc6f2cea0..35b011206 100644 --- a/Project-Euler/Problem2.js +++ b/Project-Euler/Problem2.js @@ -1,16 +1,13 @@ -const SQ5 = 5 ** 0.5 -// Square root of 5 - -const PHI = (1 + SQ5) / 2 -// definition of PHI +// https://projecteuler.net/problem=2 +const SQ5 = 5 ** 0.5 // Square root of 5 +const PHI = (1 + SQ5) / 2 // definition of PHI // theoretically it should take O(1) constant amount of time as long // arithmetic calculations are considered to be in constant amount of time -function EvenFibonacci (limit) { +const EvenFibonacci = (limit) => { const highestIndex = Math.floor(Math.log(limit * SQ5) / Math.log(PHI)) const n = Math.floor(highestIndex / 3) return ((PHI ** (3 * n + 3) - 1) / (PHI ** 3 - 1) - ((1 - PHI) ** (3 * n + 3) - 1) / ((1 - PHI) ** 3 - 1)) / SQ5 } -console.log(EvenFibonacci(4e6)) -// Sum of Even Fibonnaci upto 4 Million +console.log(EvenFibonacci(4e6)) // Sum of even Fibonacci upto 4 Million diff --git a/Project-Euler/Problem3.js b/Project-Euler/Problem3.js new file mode 100644 index 000000000..d870b80b4 --- /dev/null +++ b/Project-Euler/Problem3.js @@ -0,0 +1,20 @@ +// https://projecteuler.net/problem=3 +const problem = 600851475143 + +const largestPrime = (num) => { + let newnumm = num + let largestFact = 0 + let counter = 2 + while (counter * counter <= newnumm) { + if (newnumm % counter === 0) { + newnumm = newnumm / counter + } else { + counter++ + } + } + if (newnumm > largestFact) { + largestFact = newnumm + } + return largestFact +} +console.log(largestPrime(problem)) diff --git a/Project-Euler/Problem6.js b/Project-Euler/Problem6.js new file mode 100644 index 000000000..38dd31d95 --- /dev/null +++ b/Project-Euler/Problem6.js @@ -0,0 +1,15 @@ +// https://projecteuler.net/problem=6 + +const num = 100 // number we are checking; change to 10 to check 10 from example + +const squareDifference = (num) => { + let sumOfSquares = 0 + let sums = 0 + for (let i = 1; i <= num; i++) { + sumOfSquares += i ** 2 // add squares to the sum of squares + sums += i // add number to sum to square later + } + return (sums ** 2) - sumOfSquares // difference of square of the total sum and sum of squares +} + +console.log(squareDifference(num)) diff --git a/Project-Euler/Problem7.js b/Project-Euler/Problem7.js new file mode 100644 index 000000000..debc75276 --- /dev/null +++ b/Project-Euler/Problem7.js @@ -0,0 +1,31 @@ +// https://projecteuler.net/problem=7 +// My approach does not use the Sieve of Eratosthenes but that is another common way to approach this problem. Sieve of Atkin is another possibility as well. + +const num = 10001 +const primes = [2, 3, 5, 7, 11, 13] // given list of primes you start with + +const calculatePrime = (num) => { + // Calculate each next prime by checking each number to see what it's divisible by + let count = primes.length // count number of primes calculated + let current = primes[count - 1] + 1 // current number being assessed if prime + while (count < num) { // repeat while we haven't reached goal number of primes + // go through each prime and see if divisible by the previous primes + let prime = false + primes.some((n, i) => { + if (current % n === 0) { + return true + } + if (i === count - 1) { + prime = true + } + }) + if (prime) { // if prime, add to prime list and increment count + primes.push(current) + count += 1 + } + current += 1 + } + return primes[num - 1] +} + +console.log(calculatePrime(num)) diff --git a/Recursive/BinarySearch.js b/Recursive/BinarySearch.js new file mode 100644 index 000000000..1df6a2dec --- /dev/null +++ b/Recursive/BinarySearch.js @@ -0,0 +1,29 @@ + +// https://en.wikipedia.org/wiki/Binary_search_algorithm +// Search the integer inside the sorted integers array using Binary Search Algorithm + +const BinarySearch = (intArr, searchQuery) => { + if (searchQuery === null || searchQuery === undefined || intArr.length === 0) { + return false + } + + const middleIndex = intArr.length === 1 ? 0 : Math.ceil(intArr.length / 2) + + if (intArr[middleIndex] === searchQuery) { + return true + } else if (intArr.length > 1) { + return intArr[middleIndex] < searchQuery ? BinarySearch(intArr.slice(1, middleIndex)) : BinarySearch(intArr.slice(middleIndex)) + } else { + return false + } +} + +// testing +(() => { + console.log('Number Present with odd array length: 5 = ', BinarySearch([1, 2, 3, 4, 5, 6, 7], 5)) + console.log('Number Present with even array length: 5 = ', BinarySearch([1, 2, 4, 5, 6], 5)) + console.log('Number Present with only single element: 5 = ', BinarySearch([5], 5)) + console.log('Number Not Present: 0 = ', BinarySearch([1, 2, 3, 4, 5], 0)) + console.log('Undefined number search query = ', BinarySearch([1, 2, 3, 4, 5])) + console.log('With Empty array = ', BinarySearch([], 1)) +})() diff --git a/Recursive/Palindrome.js b/Recursive/Palindrome.js new file mode 100644 index 000000000..483fb012e --- /dev/null +++ b/Recursive/Palindrome.js @@ -0,0 +1,30 @@ + +// Check whether the given string is Palindrome or not +const Palindrome = (str) => { + if (typeof str !== 'string') { + str = str.toString() + } + + if (str === null || str === undefined) { + return false + } + + if (str.length === 1 || str.length === 0) { + return true + } + + if (str[0] !== str[str.length - 1]) { + return false + } else { + return Palindrome(str.slice(1, str.length - 1)) + } +}; + +// testing +(() => { + console.log('Palindrome: String: a = ', Palindrome('a')) + console.log('Palindrome: String: abba = ', Palindrome('abba')) + console.log('Palindrome: String: ababa = ', Palindrome('ababa')) + console.log('Not Palindrome: String: abbxa = ', Palindrome('abbxa')) + console.log('Not Palindrome: String: abxa = ', Palindrome('abxa')) +})() diff --git a/Recursive/factorial.js b/Recursive/factorial.js new file mode 100644 index 000000000..0b1260c30 --- /dev/null +++ b/Recursive/factorial.js @@ -0,0 +1,16 @@ +// function to find factorial using recursion +// example : +// 5! = 1*2*3*4*5 = 120 +// 2! = 1*2 = 2 + +const factorial = (n) => { + if (n === 0) { + return 1 + } + return n * factorial(n - 1) +} + +// testing +console.log(factorial(4)) +console.log(factorial(15)) +console.log(factorial(0)) diff --git a/Sorts/BeadSort.js b/Sorts/BeadSort.js new file mode 100644 index 000000000..1261fd554 --- /dev/null +++ b/Sorts/BeadSort.js @@ -0,0 +1,69 @@ +/** + * Bead sort (also known as Gravity sort) + * https://en.wikipedia.org/wiki/Bead_sort + * + * Does counting sort of provided array according to + * the digit represented by exp. + * Only works for arrays of positive integers. + */ + +// > beadSort([-1, 5, 8, 4, 3, 19]) +// ! RangeError: Sequence must be a list of positive integers! +// > beadSort([5, 4, 3, 2, 1]) +// [1, 2, 3, 4, 5] +// > beadSort([7, 9, 4, 3, 5]) +// [3, 4, 5, 7, 9] + +function beadSort (sequence) { + // first, let's check that our sequence consists + // of positive integers + if (sequence.some((integer) => integer < 0)) { + throw RangeError('Sequence must be a list of positive integers!') + } + + const sequenceLength = sequence.length + const max = Math.max(...sequence) + + // set initial grid + const grid = sequence.map(number => { + const maxArr = new Array(max) + + for (let i = 0; i < number; i++) { + maxArr[i] = '*' + } + + return maxArr + }) + + // drop the beads! + for (let col = 0; col < max; col++) { + let beadsCount = 0 + + for (let row = 0; row < sequenceLength; row++) { + if (grid[row][col] === '*') { + beadsCount++ + } + } + + for (let row = sequenceLength - 1; row > -1; row--) { + if (beadsCount) { + grid[row][col] = '*' + beadsCount-- + } else { + grid[row][col] = undefined + } + } + } + + // and, finally, let's turn our bead rows into their respective numbers + const sortedSequence = grid.map((beadArray) => { + const beadsArray = beadArray.filter(bead => bead === '*') + + return beadsArray.length + }) + + return sortedSequence +} + +// implementation +console.log(beadSort([5, 4, 3, 2, 1])) diff --git a/Sorts/MergeSort.js b/Sorts/MergeSort.js index ea1947d63..b634704cf 100644 --- a/Sorts/MergeSort.js +++ b/Sorts/MergeSort.js @@ -13,6 +13,27 @@ * @param {Array} list2 - sublist to break down * @return {Array} merged list */ +/* +* Doctests +* > merge([5, 4],[ 1, 2, 3]) +* [1, 2, 3, 5, 4] +* > merge([],[1, 2]) +* [1, 2] +* > merge([1, 2, 3], [1]) +* [1, 1, 2, 3] +* > merge([], []) +* [] +* +* > mergeSort([5, 4]) +* [4, 5] +* > mergeSort([8, 4, 10, 15, 9]) +* [4, 8, 9, 10, 15] +* > mergeSort([1, 2, 3]) +* [1, 2, 3] +* > mergeSort([ ]) +* [ ] +*/ + function merge (list1, list2) { var results = [] diff --git a/Sorts/QuickSort.js b/Sorts/QuickSort.js index d134b89c6..933b502ca 100644 --- a/Sorts/QuickSort.js +++ b/Sorts/QuickSort.js @@ -2,6 +2,20 @@ * Quick sort is a comparison sorting algorithm that uses a divide and conquer strategy. * For more information see here: https://en.wikipedia.org/wiki/Quicksort */ + +/* +* Doctests +* +* > quickSort([5, 4, 3, 10, 2, 1]) +* [1, 2, 3, 4, 5, 10] +* > quickSort([]) +* [] +* > quickSort([5, 4]) +* [4, 5] +* > quickSort([1, 2, 3]) +* [1, 2, 3] +*/ + function quickSort (items) { var length = items.length diff --git a/String/CheckPangram.js b/String/CheckPangram.js new file mode 100644 index 000000000..b95b0c05e --- /dev/null +++ b/String/CheckPangram.js @@ -0,0 +1,22 @@ +/* + Pangram is a sentence that contains all the letters in the alphabet + https://en.wikipedia.org/wiki/Pangram + */ + +const checkPangram = (string) => { + if (typeof string !== 'string') { + throw new TypeError('The given value is not a string') + } + + const frequency = new Set() + + for (const letter of string.toLowerCase()) { + if (letter >= 'a' && letter <= 'z') { + frequency.add(letter) + } + } + + return frequency.size === 26 +} + +export { checkPangram } diff --git a/String/CheckVowels.js b/String/CheckVowels.js new file mode 100644 index 000000000..d362d82bc --- /dev/null +++ b/String/CheckVowels.js @@ -0,0 +1,21 @@ +/* + Given a string of words or phrases, count the number of vowels. + Example: input = "hello world" return 3 + */ + +const checkVowels = (value) => { + if (typeof value !== 'string') { + throw new TypeError('The first param should be a string') + } + const vowels = ['a', 'e', 'i', 'o', 'u'] + let countVowels = 0 + for (let i = 0; i < value.length; i++) { + const char = value[i].toLowerCase() + if (vowels.includes(char)) { + countVowels++ + } + } + return countVowels +} + +export { checkVowels } diff --git a/String/CheckVowels.test.js b/String/CheckVowels.test.js new file mode 100644 index 000000000..fd074e924 --- /dev/null +++ b/String/CheckVowels.test.js @@ -0,0 +1,12 @@ +import { checkVowels } from './CheckVowels' + +describe('Test the checkVowels function', () => { + it('expect throws on use wrong param', () => { + expect(() => checkVowels(0)).toThrow() + }) + it('count the vowels in a string', () => { + const value = 'Mad World' + const countVowels = checkVowels(value) + expect(countVowels).toBe(2) + }) +}) diff --git a/String/FormatPhoneNumber.js b/String/FormatPhoneNumber.js new file mode 100644 index 000000000..c1bbde832 --- /dev/null +++ b/String/FormatPhoneNumber.js @@ -0,0 +1,17 @@ +// function that takes 10 digits and returns a string of the formatted phone number +// e.g.: 1234567890 -> (123) 456-7890 + +const formatPhoneNumber = (numbers) => { + const numbersString = numbers.toString() + if ((numbersString.length !== 10) || isNaN(numbersString)) { + // return "Invalid phone number." + throw new TypeError('Invalid phone number.') + } + const arr = '(XXX) XXX-XXXX'.split('') + Array.from(numbersString).forEach(n => { + arr[arr.indexOf('X')] = n + }) + return arr.join('') +} + +export { formatPhoneNumber } diff --git a/String/FormatPhoneNumber.test.js b/String/FormatPhoneNumber.test.js new file mode 100644 index 000000000..85291b84c --- /dev/null +++ b/String/FormatPhoneNumber.test.js @@ -0,0 +1,23 @@ +import { formatPhoneNumber } from './FormatPhoneNumber' + +describe('PhoneNumberFormatting', () => { + it('expects to return the formatted phone number', () => { + expect(formatPhoneNumber('1234567890')).toEqual('(123) 456-7890') + }) + + it('expects to return the formatted phone number', () => { + expect(formatPhoneNumber(1234567890)).toEqual('(123) 456-7890') + }) + + it('expects to throw a type error', () => { + expect(() => { formatPhoneNumber('1234567') }).toThrow('Invalid phone number.') + }) + + it('expects to throw a type error', () => { + expect(() => { formatPhoneNumber('123456text') }).toThrow('Invalid phone number.') + }) + + it('expects to throw a type error', () => { + expect(() => { formatPhoneNumber(12345) }).toThrow('Invalid phone number.') + }) +}) diff --git a/String/GenerateGUID.js b/String/GenerateGUID.js new file mode 100644 index 000000000..868819997 --- /dev/null +++ b/String/GenerateGUID.js @@ -0,0 +1,17 @@ +/* +Generates a UUID/GUID in Node.Js. +The script uses `Math.random` in combination with the timestamp for better randomness. +The function generate an RFC4122 (https://www.ietf.org/rfc/rfc4122.txt) version 4 UUID/GUID +*/ + +const Guid = () => { + const pattern = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx' + let currentDateMilliseconds = new Date().getTime() + return pattern.replace(/[xy]/g, currentChar => { + const randomChar = (currentDateMilliseconds + Math.random() * 16) % 16 | 0 + currentDateMilliseconds = Math.floor(currentDateMilliseconds / 16) + return (currentChar === 'x' ? randomChar : (randomChar & 0x7 | 0x8)).toString(16) + }) +} + +console.log(Guid()) // 'edc848db-3478-1760-8b55-7986003d895f' diff --git a/String/MaxCharacter.js b/String/MaxCharacter.js new file mode 100644 index 000000000..b7741f339 --- /dev/null +++ b/String/MaxCharacter.js @@ -0,0 +1,29 @@ +/* + Given a string of characters, return the character that appears the most often. + Example: input = "Hello World!" return "l" +*/ +const maxCharacter = (value) => { + if (typeof value !== 'string') { + throw new TypeError('The param should be a string') + } else if (!value) { + throw new Error('The param should be a valid string') + } + + const occurrences = {} + for (let i = 0; i < value.length; i++) { + const char = value[i] + if (/\s/.test(char)) continue + occurrences[char] = occurrences[char] + 1 || 1 + } + let maxCharacter = null + let maxCount = 0 + Object.keys(occurrences).forEach(char => { + if (occurrences[char] > maxCount) { + maxCount = occurrences[char] + maxCharacter = char + } + }) + return maxCharacter +} + +export { maxCharacter } diff --git a/String/MaxCharacter.test.js b/String/MaxCharacter.test.js new file mode 100644 index 000000000..d82afa039 --- /dev/null +++ b/String/MaxCharacter.test.js @@ -0,0 +1,12 @@ +import { maxCharacter } from './MaxCharacter' + +describe('Testing the maxCharacter function', () => { + it('Expect throw with wrong arg', () => { + expect(() => maxCharacter(123)).toThrow() + }) + it('Check the max character in string', () => { + const theString = 'I can\'t do that' + const maxChar = maxCharacter(theString) + expect(maxChar).toBe('t') + }) +}) diff --git a/String/PatternMatching.js b/String/PatternMatching.js index 3148f85cd..b90260ce7 100644 --- a/String/PatternMatching.js +++ b/String/PatternMatching.js @@ -24,7 +24,6 @@ const checkIfPatternExists = (text, pattern) => { // For each iteration of j check if the value of // j + 1 is equal to the length of the pattern if (j + 1 === patternLength) { - console.log(`Given pattern is found at index ${i}`) return `Given pattern is found at index ${i}` } } diff --git a/String/PermutateString.js b/String/PermutateString.js new file mode 100644 index 000000000..e470d7ac3 --- /dev/null +++ b/String/PermutateString.js @@ -0,0 +1,33 @@ +'use strict' + +const permutate = (aString) => { + if (typeof aString !== 'string' || !aString) { + throw new Error('The arg must be a valid, non empty string') + } + const characters = aString.split('') + let permutations = [[characters.shift()]] + while (characters.length) { + const currentCharacter = characters.shift() + permutations = calculateCurrentCharacterPermutation(permutations, currentCharacter) + } + return permutations + .map(character => character.join('')) + .filter((item, index, self) => (self.indexOf(item) === index)) + .sort() +} + +const calculateCurrentCharacterPermutation = (allPermutations, currentCharacter) => { + const currentPermutations = [] + allPermutations.map(permutation => { + let index = 0 + while (index <= permutation.length) { + const tmp = [...permutation] + tmp.splice(index, 0, currentCharacter) + currentPermutations.push(tmp) + index++ + } + }) + return currentPermutations +} + +export { permutate } diff --git a/String/PermutateString.test.js b/String/PermutateString.test.js new file mode 100644 index 000000000..71df87b5e --- /dev/null +++ b/String/PermutateString.test.js @@ -0,0 +1,17 @@ +import { permutate } from './PermutateString' + +describe('Permutate a string', () => { + it('expects to throw an Error with an empty string', () => { + expect(() => { permutate() }).toThrow('The arg must be a valid, non empty string') + }) + it('expects to permute "no" into [no, on]', () => { + expect(['no', 'on']).toEqual(permutate('no')) + }) + it('expects to permute "yes" into [esy, eys, sey, sye, yes, yse]', () => { + expect(['esy', 'eys', 'sey', 'sye', 'yes', 'yse']).toEqual(permutate('yes')) + }) + it('expects to permute "good" into [dgoo dogo doog gdoo godo good odgo odog ogdo ogod oodg oogd ]', () => { + expect(['dgoo', 'dogo', 'doog', 'gdoo', 'godo', 'good', 'odgo', 'odog', 'ogdo', 'ogod', 'oodg', 'oogd']) + .toEqual(permutate('good')) + }) +}) diff --git a/String/ValidateEmail.js b/String/ValidateEmail.js new file mode 100644 index 000000000..af2ee3f09 --- /dev/null +++ b/String/ValidateEmail.js @@ -0,0 +1,19 @@ +/* + function that takes a string input and return either it is true of false + a valid email address + e.g.: mahfoudh.arous@gmail.com -> true + e.g.: mahfoudh.arous.com ->false +*/ + +const validateEmail = (str) => { + if (str === '' || str === null) { + throw new TypeError('Email Address String Null or Empty.') + } + if (str.startsWith('@') === true || !str.includes('@') || !str.endsWith('.com')) { + return false + } + + return true +} + +export { validateEmail } diff --git a/String/ValidateEmail.test.js b/String/ValidateEmail.test.js new file mode 100644 index 000000000..a10f8279c --- /dev/null +++ b/String/ValidateEmail.test.js @@ -0,0 +1,19 @@ +import { validateEmail } from './ValidateEmail' + +describe('Validation of an Email Address', () => { + it('expects to return false', () => { + expect(validateEmail('mahfoudh.arous.com')).toEqual(false) + }) + + it('expects to return false', () => { + expect(validateEmail('mahfoudh.arous@com')).toEqual(false) + }) + + it('expects to return true', () => { + expect(validateEmail('mahfoudh.arous@gmail.com')).toEqual(true) + }) + + it('expects to throw a type error', () => { + expect(() => { validateEmail('') }).toThrow('Email Address String Null or Empty.') + }) +}) diff --git a/String/createPurmutations.js b/String/createPurmutations.js new file mode 100644 index 000000000..1b3cbb06a --- /dev/null +++ b/String/createPurmutations.js @@ -0,0 +1,37 @@ +/* +a permutation of a set is, loosely speaking, an arrangement of its members into a sequence or linear order, or if the set is already ordered, a rearrangement of its elements. +The word "permutation" also refers to the act or process of changing the linear order of an ordered set +More at : https://en.wikipedia.org/wiki/Permutation +*/ + +const createPermutations = (str) => { +// convert string to array + const arr = str.split('') + + // get array length + const strLen = arr.length + // this will hold all the permutations + const perms = [] + let rest + let picked + let restPerms + let next + + // if strLen is zero, return the same string + if (strLen === 0) { return [str] } + // loop to the length to get all permutations + for (let i = 0; i < strLen; i++) { + rest = Object.create(arr) + picked = rest.splice(i, 1) + + restPerms = createPermutations(rest.join('')) + + for (let j = 0, jLen = restPerms.length; j < jLen; j++) { + next = picked.concat(restPerms[j]) + perms.push(next.join('')) + } + } + return perms +} + +console.log(createPermutations('abc')) // should print ["abc", "acb", "bac", "bca", "cab", "cba"] diff --git a/String/CheckAnagram.test.js b/String/test/CheckAnagram.test.js similarity index 92% rename from String/CheckAnagram.test.js rename to String/test/CheckAnagram.test.js index e5016f752..691d5ba89 100644 --- a/String/CheckAnagram.test.js +++ b/String/test/CheckAnagram.test.js @@ -1,4 +1,4 @@ -import { checkAnagram } from './CheckAnagram' +import { checkAnagram } from '../CheckAnagram' describe('checkAnagram', () => { it.each` @@ -18,7 +18,7 @@ describe('checkAnagram', () => { ) it('expects to return "Not anagram" if the arguments have different lengths', () => { const SUT = checkAnagram('abs', 'abds') - expect(SUT).toBe('Not Anagram') + expect(SUT).toBe('Not anagrams') }) it('expects to return "Not anagram" if the arguments are not anagrams', () => { const SUT = checkAnagram('abcs', 'abds') diff --git a/String/CheckPalindrome.test.js b/String/test/CheckPalindrome.test.js similarity index 90% rename from String/CheckPalindrome.test.js rename to String/test/CheckPalindrome.test.js index 3bd401ba1..cfe88f7e5 100644 --- a/String/CheckPalindrome.test.js +++ b/String/test/CheckPalindrome.test.js @@ -1,4 +1,4 @@ -import { checkPalindrome } from './CheckPalindrome' +import { checkPalindrome } from '../CheckPalindrome' describe('checkPalindrome', () => { it('expects to return "Palindrome" if the given string is a palindrome', () => { diff --git a/String/test/CheckPangram.test.js b/String/test/CheckPangram.test.js new file mode 100644 index 000000000..f062ed44f --- /dev/null +++ b/String/test/CheckPangram.test.js @@ -0,0 +1,33 @@ +import { checkPangram } from '../CheckPangram' + +describe('checkPangram', () => { + it('"The quick brown fox jumps over the lazy dog" is a pangram', () => { + expect( + checkPangram('The quick brown fox jumps over the lazy dog') + ).toBeTruthy() + }) + + it('"Waltz, bad nymph, for quick jigs vex." is a pangram', () => { + expect(checkPangram('Waltz, bad nymph, for quick jigs vex.')).toBeTruthy() + }) + + it('"Jived fox nymph grabs quick waltz." is a pangram', () => { + expect(checkPangram('Jived fox nymph grabs quick waltz.')).toBeTruthy() + }) + + it('"My name is Unknown" is NOT a pangram', () => { + expect(checkPangram('My name is Unknown')).toBeFalsy() + }) + + it('"The quick brown fox jumps over the la_y dog" is NOT a pangram', () => { + expect( + checkPangram('The quick brown fox jumps over the la_y dog') + ).toBeFalsy() + }) + + it('Throws an error if given param is not a string', () => { + expect(() => { + checkPangram(undefined) + }).toThrow('The given value is not a string') + }) +}) diff --git a/String/PatternMatching.test.js b/String/test/PatternMatching.test.js similarity index 84% rename from String/PatternMatching.test.js rename to String/test/PatternMatching.test.js index 23e892dd7..d0eab80b6 100644 --- a/String/PatternMatching.test.js +++ b/String/test/PatternMatching.test.js @@ -1,4 +1,4 @@ -import { checkIfPatternExists } from './PatternMatching' +import { checkIfPatternExists } from '../PatternMatching' describe('checkIfPatternExists', () => { it('expects to find a pattern with correct input', () => { const text = 'AABAACAADAABAAAABAA' @@ -21,6 +21,8 @@ describe('checkIfPatternExists', () => { it('expects to throw an error message when given inpuut is not a string', () => { const text = 123444456 const pattern = 123 - expect(() => checkIfPatternExists(text, pattern)).toThrow('Given input is not a string') + expect(() => checkIfPatternExists(text, pattern)).toThrow( + 'Given input is not a string' + ) }) }) diff --git a/String/ReverseString.test.js b/String/test/ReverseString.test.js similarity index 98% rename from String/ReverseString.test.js rename to String/test/ReverseString.test.js index 1658c8bde..6ec1bb4df 100644 --- a/String/ReverseString.test.js +++ b/String/test/ReverseString.test.js @@ -1,7 +1,7 @@ import { ReverseStringIterative, ReverseStringIterativeInplace -} from './ReverseString' +} from '../ReverseString' describe('ReverseStringIterative', () => { it('expects to reverse a simple string', () => { diff --git a/String/ReverseWords.test.js b/String/test/ReverseWords.test.js similarity index 90% rename from String/ReverseWords.test.js rename to String/test/ReverseWords.test.js index 7c4aa16dd..32bd9d462 100644 --- a/String/ReverseWords.test.js +++ b/String/test/ReverseWords.test.js @@ -1,4 +1,4 @@ -import { reverseWords } from './ReverseWords' +import { reverseWords } from '../ReverseWords' describe('reverseWords', () => { it('expects to reverse words to return a joined word', () => { diff --git a/Timing-Functions/GetMonthDays.js b/Timing-Functions/GetMonthDays.js new file mode 100644 index 000000000..fcf5604d3 --- /dev/null +++ b/Timing-Functions/GetMonthDays.js @@ -0,0 +1,33 @@ +/** + function that takes month number and its year and returns the number of days within it + * @param monthNumber. + * @param year. + e.g.: mahfoudh.arous@gmail.com -> true + e.g.: mahfoudh.arous.com ->false +*/ + +const getMonthDays = (monthNumber, year) => { + const the31DaysMonths = [1, 3, 5, 7, 8, 10, 12] + const the30DaysMonths = [4, 6, 9, 11] + + if (!the31DaysMonths.includes(monthNumber) && !the30DaysMonths.includes(monthNumber) && + (monthNumber !== 2) + ) { + throw new TypeError('Invalid Month Number.') + } + + if (the31DaysMonths.includes(monthNumber)) { return 31 } + + if (the30DaysMonths.includes(monthNumber)) { return 30 } + + // Check for Leap year + if (year % 4 === 0) { + if ((year % 100 !== 0) || (year % 100 === 0 && year % 400 === 0)) { + return 29 + } + } + + return 28 +} + +export { getMonthDays } diff --git a/Timing-Functions/GetMonthDays.test.js b/Timing-Functions/GetMonthDays.test.js new file mode 100644 index 000000000..2be43982c --- /dev/null +++ b/Timing-Functions/GetMonthDays.test.js @@ -0,0 +1,19 @@ +import { getMonthDays } from './GetMonthDays' + +describe('Get the Days of a Month', () => { + it('expects to return 28', () => { + expect(getMonthDays(2, 2018)).toEqual(28) + }) + + it('expects to return 30', () => { + expect(getMonthDays(6, 254)).toEqual(30) + }) + + it('expects to return 29', () => { + expect(getMonthDays(2, 2024)).toEqual(29) + }) + + it('expects to throw a type error', () => { + expect(() => { getMonthDays(13, 2020) }).toThrow('Invalid Month Number.') + }) +}) diff --git a/Trees/BreadthFirstTreeTraversal.js b/Trees/BreadthFirstTreeTraversal.js new file mode 100644 index 000000000..f81cf24e6 --- /dev/null +++ b/Trees/BreadthFirstTreeTraversal.js @@ -0,0 +1,66 @@ +/* + Breadth First Tree Traversal or level order traversal implementation in javascript + Author: @GerardUbuntu +*/ + +class Node { + constructor (data) { + this.data = data + this.left = null + this.right = null + } +} + +class BinaryTree { + constructor () { + this.root = null + this.traversal = [] + } + + breadthFirst () { + const h = this.getHeight(this.root) + for (let i = 1; i <= h; i++) { + this.traverseLevel(this.root, i) + } + return this.traversal.toLocaleString() + } + + // Compputing the height of the tree + getHeight (node) { + if (node == null) { + return 0 + } else { + const lheight = this.getHeight(node.left) + const rheight = this.getHeight(node.right) + return lheight > rheight ? lheight + 1 : rheight + 1 + } + } + + traverseLevel (node, level) { + if (level === 1 && node !== null) { + this.traversal.push(node.data) + } else { + if (node !== null) { + this.traverseLevel(node.left, level - 1) + this.traverseLevel(node.right, level - 1) + } + } + } +} + +const binaryTree = new BinaryTree() +const root = new Node(7) +root.left = new Node(5) +root.right = new Node(8) +root.left.left = new Node(3) +root.left.right = new Node(6) +root.right.right = new Node(9) +binaryTree.root = root + +console.log(binaryTree.breadthFirst()) + +// 7 +// / \ +// 5 8 +// / \ \ +// 3 6 9 diff --git a/package-lock.json b/package-lock.json index 20ddcf663..54a856664 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5815,6 +5815,19 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "node": { + "version": "14.13.1", + "resolved": "https://registry.npmjs.org/node/-/node-14.13.1.tgz", + "integrity": "sha512-X8oMUs+fSAr+uTrVqiaunZPvXRVkVvo5J+6I1N01nlG7H+wmckYtvgxUBCBWo5HD1xAyL2vbIiwU+qW9ascTQg==", + "requires": { + "node-bin-setup": "^1.0.0" + } + }, + "node-bin-setup": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/node-bin-setup/-/node-bin-setup-1.0.6.tgz", + "integrity": "sha512-uPIxXNis1CRbv1DwqAxkgBk5NFV3s7cMN/Gf556jSw6jBvV7ca4F9lRL/8cALcZecRibeqU+5dFYqFFmzv5a0Q==" + }, "node-fetch": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", @@ -7593,9 +7606,9 @@ } }, "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, "tunnel-agent": { diff --git a/package.json b/package.json index 450a58349..729e6f71b 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "@babel/plugin-transform-runtime": "^7.11.5", "@babel/preset-env": "^7.11.5", "jsdom": "^16.3.0", + "node": "^14.13.1", "node-fetch": "2.6.1" }, "standard": {