diff --git a/Conversions/BinaryToDecimal.js b/Conversions/BinaryToDecimal.js index 907468470..4a391cf84 100644 --- a/Conversions/BinaryToDecimal.js +++ b/Conversions/BinaryToDecimal.js @@ -1,11 +1,14 @@ -function binaryToDeicmal (binaryNumber) { +const binaryToDecimal = (binaryString) => { let decimalNumber = 0 - const binaryDigits = binaryNumber.split('').reverse() // Splits the binary number into reversed single digits + const binaryDigits = binaryString.split('').reverse() // Splits the binary number into reversed single digits binaryDigits.forEach((binaryDigit, index) => { decimalNumber += binaryDigit * (Math.pow(2, index)) // Summation of all the decimal converted digits }) - console.log(`Decimal of ${binaryNumber} is ${decimalNumber}`) + console.log(`Decimal of ${binaryString} is ${decimalNumber}`) + return decimalNumber } -binaryToDeicmal('111001') -binaryToDeicmal('101') +(() => { + binaryToDecimal('111001') + binaryToDecimal('101') +})() diff --git a/DIRECTORY.md b/DIRECTORY.md index e447facda..475f2bac3 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -34,7 +34,9 @@ * [MaxHeap](https://github.com/TheAlgorithms/Javascript/blob/master/Data-Structures/Heap/MaxHeap.js) * [MinPriorityQueue](https://github.com/TheAlgorithms/Javascript/blob/master/Data-Structures/Heap/MinPriorityQueue.js) * Linked-List + * [CycleDetection](https://github.com/TheAlgorithms/Javascript/blob/master/Data-Structures/Linked-List/CycleDetection.js) * [DoublyLinkedList](https://github.com/TheAlgorithms/Javascript/blob/master/Data-Structures/Linked-List/DoublyLinkedList.js) + * [SingleCircularLinkedList](https://github.com/TheAlgorithms/Javascript/blob/master/Data-Structures/Linked-List/SingleCircularLinkedList.js.js) * [SinglyLinkList](https://github.com/TheAlgorithms/Javascript/blob/master/Data-Structures/Linked-List/SinglyLinkList.js) * Queue * [Queue](https://github.com/TheAlgorithms/Javascript/blob/master/Data-Structures/Queue/Queue.js) @@ -50,6 +52,7 @@ * [ClimbingStairs](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/ClimbingStairs.js) * [CoinChange](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/CoinChange.js) * [EditDistance](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/EditDistance.js) + * [FibonacciNumber](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/FibonacciNumber.js) * [KadaneAlgo](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/KadaneAlgo.js) * [LevenshteinDistance](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/LevenshteinDistance.js) * [LongestCommonSubsequence](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/LongestCommonSubsequence.js) @@ -87,6 +90,7 @@ * [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) + * [MeanSquareError](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/MeanSquareError.js) * [ModularBinaryExponentiationRecursive](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/ModularBinaryExponentiationRecursive.js) * [Palindrome](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/Palindrome.js) * [PascalTriangle](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/PascalTriangle.js) @@ -101,6 +105,7 @@ ## Recursive * [EucledianGCD](https://github.com/TheAlgorithms/Javascript/blob/master/Recursive/EucledianGCD.js) + * [FibonacciNumberRecursive](https://github.com/TheAlgorithms/Javascript/blob/master/Recursive/FibonacciNumberRecursive.js) * [TowerOfHanoi](https://github.com/TheAlgorithms/Javascript/blob/master/Recursive/TowerOfHanoi.js) ## Search @@ -130,6 +135,7 @@ * [QuickSort](https://github.com/TheAlgorithms/Javascript/blob/master/Sorts/QuickSort.js) * [RadixSort](https://github.com/TheAlgorithms/Javascript/blob/master/Sorts/RadixSort.js) * [SelectionSort](https://github.com/TheAlgorithms/Javascript/blob/master/Sorts/SelectionSort.js) + * [SelectionSort](https://github.com/TheAlgorithms/Javascript/blob/master/Sorts/SelectionSort.test.js) * [ShellSort](https://github.com/TheAlgorithms/Javascript/blob/master/Sorts/ShellSort.js) * [TimSort](https://github.com/TheAlgorithms/Javascript/blob/master/Sorts/TimSort.js) * [TopologicalSort](https://github.com/TheAlgorithms/Javascript/blob/master/Sorts/TopologicalSort.js) @@ -141,6 +147,8 @@ * [CheckPalindrome](https://github.com/TheAlgorithms/Javascript/blob/master/String/CheckPalindrome.js) * [CheckPalindrome](https://github.com/TheAlgorithms/Javascript/blob/master/String/CheckPalindrome.test.js) * [CheckRearrangePalindrome](https://github.com/TheAlgorithms/Javascript/blob/master/String/CheckRearrangePalindrome.js) + * [CheckWordOccurrence](https://github.com/TheAlgorithms/Javascript/blob/master/String/CheckWordOccurrence.js) + * [CheckWordOcurrence](https://github.com/TheAlgorithms/Javascript/blob/master/String/CheckWordOcurrence.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) * [ReverseString](https://github.com/TheAlgorithms/Javascript/blob/master/String/ReverseString.js) diff --git a/Data-Structures/Linked-List/CycleDetection.js b/Data-Structures/Linked-List/CycleDetection.js new file mode 100644 index 000000000..910fe2214 --- /dev/null +++ b/Data-Structures/Linked-List/CycleDetection.js @@ -0,0 +1,32 @@ +/** + * A LinkedList based solution for Detect a Cycle in a list + * https://en.wikipedia.org/wiki/Cycle_detection + */ + +function main () { + /* + Problem Statement: + Given head, the head of a linked list, determine if the linked list has a cycle in it. + + Note: + * While Solving the problem in given link below, don't use main() function. + * Just use only the code inside main() function. + * The purpose of using main() function here is to aviod global variables. + + Link for the Problem: https://leetcode.com/problems/linked-list-cycle/ + */ + const head = '' // Reference to head is given in the problem. So please ignore this line + let fast = head + let slow = head + + while (fast != null && fast.next != null && slow != null) { + fast = fast.next.next + slow = slow.next + if (fast === slow) { + return true + } + } + return false +} + +main() diff --git a/Data-Structures/Linked-List/SingleCircularLinkedList.js.js b/Data-Structures/Linked-List/SingleCircularLinkedList.js.js new file mode 100644 index 000000000..fd50253ad --- /dev/null +++ b/Data-Structures/Linked-List/SingleCircularLinkedList.js.js @@ -0,0 +1,97 @@ +class Node { + constructor (data, next = null) { + this.data = data + this.next = next + } +} + +class SinglyCircularLinkedList { + constructor () { + this.head = null + this.size = 0 + } + + insert (data) { + const node = new Node(data) + + if (!this.head) { + node.next = node + this.head = node + this.size++ + } else { + node.next = this.head + + let current = this.head + + while (current.next.data !== this.head.data) { + current = current.next + } + + current.next = node + this.size++ + } + } + + insertAt (index, data) { + const node = new Node(data) + + if (index < 0 || index > this.size) return + + if (index === 0) { + this.head = node + this.size = 1 + return + } + + let previous + let count = 0 + let current = this.head + + while (count < index) { + previous = current + current = current.next + count++ + } + + node.next = current + previous.next = node + this.size++ + } + + remove () { + if (!this.head) return + + let prev + let current = this.head + + while (current.next !== this.head) { + prev = current + current = current.next + } + + prev.next = this.head + this.size-- + } + + printData () { + let count = 0 + let current = this.head + + while (current !== null && count !== this.size) { + console.log(current.data + '\n') + current = current.next + count++ + } + } +} + +const ll = new SinglyCircularLinkedList() + +ll.insert(10) +ll.insert(20) +ll.insert(30) +ll.insert(40) +ll.insert(50) +ll.insertAt(5, 60) +ll.remove(5) +ll.printData() diff --git a/Dynamic-Programming/FibonacciNumber.js b/Dynamic-Programming/FibonacciNumber.js new file mode 100644 index 000000000..a39912f18 --- /dev/null +++ b/Dynamic-Programming/FibonacciNumber.js @@ -0,0 +1,18 @@ +// https://en.wikipedia.org/wiki/Fibonacci_number + +const fibonacci = (N) => { + // creating array to store values + const memo = new Array(N + 1) + memo[0] = 0 + memo[1] = 1 + for (let i = 2; i <= N; i++) { + memo[i] = memo[i - 1] + memo[i - 2] + } + return memo[N] +} + +// testing +(() => { + const number = 5 + console.log(number + 'th Fibonacci number is ' + fibonacci(number)) +})() diff --git a/Maths/MeanSquareError.js b/Maths/MeanSquareError.js new file mode 100644 index 000000000..de9dcfd7f --- /dev/null +++ b/Maths/MeanSquareError.js @@ -0,0 +1,26 @@ +// Wikipedia: https://en.wikipedia.org/wiki/Mean_squared_error + +const meanSquaredError = (predicted, expected) => { + if (!Array.isArray(predicted) || !Array.isArray(expected)) { + throw new TypeError('Argument must be an Array') + } + + if (predicted.length !== expected.length) { + throw new TypeError('The two lists must be of equal length') + } + + let err = 0 + + for (let i = 0; i < expected.length; i++) { + err += (expected[i] - predicted[i]) ** 2 + } + + 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) +})() diff --git a/Recursive/FibonacciNumberRecursive.js b/Recursive/FibonacciNumberRecursive.js new file mode 100644 index 000000000..e5c5bb95b --- /dev/null +++ b/Recursive/FibonacciNumberRecursive.js @@ -0,0 +1,13 @@ +// https://en.wikipedia.org/wiki/Fibonacci_number + +const fibonacci = (N) => { + if (N === 0 || N === 1) return N + + return fibonacci(N - 2) + fibonacci(N - 1) +} + +// testing +(() => { + const number = 5 + console.log(number + 'th Fibonacci number is ' + fibonacci(number)) +})() diff --git a/Sorts/SelectionSort.js b/Sorts/SelectionSort.js index 38a4bfff2..c4a11e354 100644 --- a/Sorts/SelectionSort.js +++ b/Sorts/SelectionSort.js @@ -8,12 +8,19 @@ *from the unsorted subarray is picked and moved to the sorted subarray. */ -function selectionSort (items) { - var length = items.length - for (var i = 0; i < length - 1; i++) { +const selectionSort = (list) => { + if (!Array.isArray(list)) { + throw new TypeError('Given input is not an array') + } + const items = [...list] // We don't want to modify the original array + const length = items.length + for (let i = 0; i < length - 1; i++) { + if (typeof items[i] !== 'number') { + throw new TypeError('One of the items in your array is not a number') + } // Number of passes - var min = i // min holds the current minimum number position for each pass; i holds the Initial min number - for (var j = i + 1; j < length; j++) { // Note that j = i + 1 as we only need to go through unsorted array + let min = i // min holds the current minimum number position for each pass; i holds the Initial min number + for (let j = i + 1; j < length; j++) { // Note that j = i + 1 as we only need to go through unsorted array if (items[j] < items[min]) { // Compare the numbers min = j // Change the current min number position if a smaller num is found } @@ -21,16 +28,23 @@ function selectionSort (items) { if (min !== i) { // After each pass, if the current min num != initial min num, exchange the position. // Swap the numbers - [items[i], items[min]] = [items[min], [items[i]]] + [items[i], items[min]] = [items[min], items[i]] } } + return items } -// Implementation of Selection Sort +/* Implementation of Selection Sort -var ar = [5, 6, 7, 8, 1, 2, 12, 14] -// Array before Sort -console.log(ar) -selectionSort(ar) -// Array after sort -console.log(ar) +(() => { + let array = [5, 6, 7, 8, 1, 2, 12, 14] + // Array before Sort + console.log(array) + array = selectionSort(array) + // Array after sort + console.log(array) +})() + +*/ + +export { selectionSort } diff --git a/Sorts/SelectionSort.test.js b/Sorts/SelectionSort.test.js new file mode 100644 index 000000000..57ad1e8ec --- /dev/null +++ b/Sorts/SelectionSort.test.js @@ -0,0 +1,22 @@ +import { selectionSort } from './SelectionSort' + +describe('selectionSort', () => { + it('expects to return the array sorted in ascending order', () => { + var toSort = [5, 6, 7, 8, 1, 2, 12, 14] + const expected = [1, 2, 5, 6, 7, 8, 12, 14] + + expect(selectionSort(toSort)).toEqual(expected) + }) + + it('expects to throw if it is not a valid array', () => { + expect(() => selectionSort('abc')).toThrow('Given input is not an array') + expect(() => selectionSort(123)).toThrow('Given input is not an array') + expect(() => selectionSort({})).toThrow('Given input is not an array') + expect(() => selectionSort(null)).toThrow('Given input is not an array') + expect(() => selectionSort()).toThrow('Given input is not an array') + }) + + it('expects to throw if one of the elements in the array is not a number', () => { + expect(() => selectionSort([1, 'x', 2])).toThrow('One of the items in your array is not a number') + }) +}) diff --git a/String/CheckWordOccurrence.js b/String/CheckWordOccurrence.js new file mode 100644 index 000000000..b86150c0b --- /dev/null +++ b/String/CheckWordOccurrence.js @@ -0,0 +1,25 @@ +/** + * Check and count occurrence of each word in a string + * Inputs a String eg. Madonna and Boolean + **/ + +const checkWordOccurrence = (str, isCaseSensitive = false) => { + if (typeof str !== 'string') { + throw new TypeError('The first param should be a string') + } + if (typeof isCaseSensitive !== 'boolean') { + throw new TypeError('The second param should be a boolean') + } + + const result = {} + if (str.length > 0) { + for (let i = 0; i < str.length; i++) { + const word = isCaseSensitive ? str[i] : str[i].toUpperCase() + if (/\s/.test(word)) continue + result[word] = (!result[word]) ? 1 : result[word] + 1 + } + } + + return result +} +export { checkWordOccurrence } diff --git a/String/CheckWordOcurrence.test.js b/String/CheckWordOcurrence.test.js new file mode 100644 index 000000000..2b1a88782 --- /dev/null +++ b/String/CheckWordOcurrence.test.js @@ -0,0 +1,33 @@ +import { checkWordOccurrence } from './CheckWordOccurrence' +describe('checkWordOccurrence', () => { + it('expects throw on insert wrong string', () => { + const value = 123 + expect(() => checkWordOccurrence(value)).toThrow() + }) + it('expect throw on insert wrong param for case sensitive', () => { + const value = 'hello' + expect(() => checkWordOccurrence(value, value)).toThrow() + }) + it('check occurrence with case sensitive', () => { + const stringToTest = 'A Mad World' + const charsOccurrences = checkWordOccurrence(stringToTest, true) + const expectResult = { A: 1, M: 1, a: 1, d: 2, W: 1, l: 1, o: 1, r: 1 } + const occurrencesObjectKeys = Object.keys(charsOccurrences) + const expectObjectKeys = Object.keys(expectResult) + expect(occurrencesObjectKeys.length).toBe(expectObjectKeys.length) + expectObjectKeys.forEach(key => { + expect(expectResult[key]).toBe(charsOccurrences[key]) + }) + }) + it('check occurrence with case insensitive', () => { + const stringToTest = 'A Mad World' + const charsOccurrences = checkWordOccurrence(stringToTest, false) + const expectResult = { A: 2, D: 2, L: 1, M: 1, O: 1, R: 1, W: 1 } + const occurrencesObjectKeys = Object.keys(charsOccurrences) + const expectObjectKeys = Object.keys(expectResult) + expect(occurrencesObjectKeys.length).toBe(expectObjectKeys.length) + expectObjectKeys.forEach(key => { + expect(expectResult[key]).toBe(charsOccurrences[key]) + }) + }) +}) diff --git a/package-lock.json b/package-lock.json index 9bcf2855d..20ddcf663 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3734,12 +3734,11 @@ }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, diff --git a/package.json b/package.json index eea349d1b..450a58349 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,9 @@ "node-fetch": "2.6.1" }, "standard": { - "env": [ "jest" ] + "env": [ + "jest" + ] }, "devDependencies": { "babel-jest": "^26.3.0",