From 986bb8ea89135fbc65a7a0e1a3a81de76c90895e Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Sun, 27 Dec 2020 19:49:12 +0200 Subject: [PATCH 01/28] Add Levenshtein distance --- snippets/levenshteinDistance.md | 41 +++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 snippets/levenshteinDistance.md diff --git a/snippets/levenshteinDistance.md b/snippets/levenshteinDistance.md new file mode 100644 index 000000000..ad33293ef --- /dev/null +++ b/snippets/levenshteinDistance.md @@ -0,0 +1,41 @@ +--- +title: levenshteinDistance +tags: string,algorithm,intermediate +--- + +Calculates the difference between two strings. + +- If either of the two strings has a `length` of zero, return the `length` of the other one. +- Use a `for` loop to iterate over the letters of the target string and a nested `for` loop to iterate over the letters of the source string. +- Calculate the cost of substituting the letters corresponding to `i - 1` and `j - 1` in the target and source respectively (`0` if they are the same, `1` otherwise). +- Use `Math.min()` to populate each element in the 2D array with the minimum of the cell above incremented by one, the cell to the left incremented by one or the cell to the top left incremented by the previously calculated cost. +- Return the last element of the last row of the produced array. + +```js +const levenshteinDistance = (s, t) => { + if (!s.length) return t.length; + if (!t.length) return s.length; + + const arr = []; + + for (let i = 0; i <= t.length; i++) { + arr[i] = [i]; + for (let j = 1; j <= s.length; j++) { + arr[i][j] = + i === 0 + ? j + : Math.min( + arr[i - 1][j] + 1, + arr[i][j - 1] + 1, + arr[i - 1][j - 1] + (s[j - 1] === t[i - 1] ? 0 : 1) + ); + } + } + + return arr[t.length][s.length]; +}; +``` + +```js +levenshteinDistance('duck', 'dark'); // 2 +``` From 5c30fac74f39120a96267e548b90cbe0cac7b80e Mon Sep 17 00:00:00 2001 From: Isabelle Viktoria Maciohsek Date: Sun, 27 Dec 2020 21:20:31 +0200 Subject: [PATCH 02/28] Add bubble sort --- snippets/bubbleSort.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 snippets/bubbleSort.md diff --git a/snippets/bubbleSort.md b/snippets/bubbleSort.md new file mode 100644 index 000000000..8e0396284 --- /dev/null +++ b/snippets/bubbleSort.md @@ -0,0 +1,41 @@ +--- +title: bubbleSort +tags: algorithm,array,beginner +--- + +Sorts an array of numbers, using the bubble sort algorithm. + +- Declare a variable, `swapped`, that indicates if any values were swapped during the current iteration. +- Use the spread operator (`...`) to clone the original array, `arr`. +- Use a `for` loop to iterate over the elements of the cloned array, terminating before the last element. +- Use a nested `for` loop to iterate over the segment of the array between `0` and `i`, swapping any adjacent out of order elements and setting `swapped` to `true`. +- If `swapped` is `false` after an iteration, no more changes are needed, so the cloned array is returned. + +```js +const bubbleSort = arr => { + let swapped = false; + + const a = [...arr]; + + for (let i = 1; i < a.length - 1; i++) { + swapped = false; + + for (let j = 0; j < a.length - i; j++) { + if (a[j + 1] < a[j]) { + [a[j], a[j + 1]] = [a[j + 1], a[j]]; + swapped = true; + } + } + + if (!swapped) { + return a; + } + } + + return a; +}; +``` + +```js +bubbleSort([2, 1, 4, 3]); // [1, 2, 3, 4] +``` From 67593d59bca2566b0bd50276efacf287bcb0a415 Mon Sep 17 00:00:00 2001 From: Isabelle Viktoria Maciohsek Date: Sun, 27 Dec 2020 21:52:43 +0200 Subject: [PATCH 03/28] Add quicksort --- snippets/quickSort.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 snippets/quickSort.md diff --git a/snippets/quickSort.md b/snippets/quickSort.md new file mode 100644 index 000000000..c6dc6c4fe --- /dev/null +++ b/snippets/quickSort.md @@ -0,0 +1,41 @@ +--- +title: quickSort +tags: algorithm,array,recursion,advanced +--- + +Sorts an array of numbers, using the quicksort algorithm. + +- Use recursion. +- Use the spread operator (`...`) to clone the original array, `arr`. +- If the `length` of the array is less than `2`, return the cloned array. +- Use `Math.floor()` to calculate the index of the pivot element. +- Use `Array.prototype.reduce()` and `Array.prototype.push()` to split the array into two subarrays (elements smaller or equal to the `pivot` and elements greater than it), destructuring the result into two arrays. +- Recursively call `quickSort()` on the created subarrays. + +```js +const quickSort = arr => { + const a = [...arr]; + + if (a.length < 2) return a; + + const pivotIndex = Math.floor(arr.length / 2); + const pivot = a[pivotIndex]; + const [lo, hi] = a.reduce( + (acc, val, i) => { + if (val < pivot || (val === pivot && i != pivotIndex)) { + acc[0].push(val); + } else if (val > pivot) { + acc[1].push(val); + } + return acc; + }, + [[], []] + ); + + return [...quickSort(lo), pivot, ...quickSort(hi)]; +}; +``` + +```js +quickSort([1, 6, 1, 5, 3, 2, 1, 4]); // [1, 1, 1, 2, 3, 4, 5, 6] +``` From 8e722c5cab329286d177bce6599422bdc9cce9c5 Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Sun, 27 Dec 2020 22:22:44 +0200 Subject: [PATCH 04/28] Add selectionSort --- snippets/selectionSort.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 snippets/selectionSort.md diff --git a/snippets/selectionSort.md b/snippets/selectionSort.md new file mode 100644 index 000000000..1ac735fc8 --- /dev/null +++ b/snippets/selectionSort.md @@ -0,0 +1,29 @@ +--- +title: selectionSort +tags: algorithm,array,intermediate +--- + +Sorts an array of numbers, using the selection sort algorithm. + +- Use the spread operator (`...`) to clone the original array, `arr`. +- Use a `for` loop to iterate over elements in the array. +- Use `Array.prototype.slice()` and `Array.prototype.reduce()` to find the index of the minimum element in the subarray to the right of the current index and perform a swap, if necessary. + +```js +const selectionSort = arr => { + const a = [...arr]; + + for (let i = 0; i < a.length; i++) { + const min = a + .slice(i + 1) + .reduce((acc, val, j) => (val < a[acc] ? j + i + 1 : acc), i); + if (min !== i) [a[i], a[min]] = [a[min], a[i]]; + } + + return a; +}; +``` + +```js +selectionSort([5, 1, 4, 2, 3]); // [1, 2, 3, 4, 5] +``` From 8688d810f8f425a2dca93e1e902aa3eccd9af4f8 Mon Sep 17 00:00:00 2001 From: Isabelle Viktoria Maciohsek Date: Sun, 27 Dec 2020 22:44:32 +0200 Subject: [PATCH 05/28] Add mergesort --- snippets/mergeSort.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 snippets/mergeSort.md diff --git a/snippets/mergeSort.md b/snippets/mergeSort.md new file mode 100644 index 000000000..4c6e916e7 --- /dev/null +++ b/snippets/mergeSort.md @@ -0,0 +1,30 @@ +--- +title: mergeSort +tags: algorithm,array,recursion,advanced +--- + +Sorts an array of numbers, using the merge sort algorithm. + +- Use recursion. +- If the `length` of the array is less than `2`, return the array. +- Use `Math.floor()` to calculate the middle point of the array. +- Use `Array.prototype.slice()` to slice the array in two and recursively call `mergeSort()` on the created subarrays. +- Finally, use `Array.from()` and `Array.prototype.shift()` to combine the two sorted subarrays into one. + +```js +const mergeSort = arr => { + if (arr.length < 2) return arr; + const mid = Math.floor(arr.length / 2); + const l = mergeSort(arr.slice(0, mid)); + const r = mergeSort(arr.slice(mid, arr.length)); + return Array.from({ length: l.length + r.length }, () => { + if (!l.length) return r.shift(); + else if (!r.length) return l.shift(); + else return l[0] > r[0] ? r.shift() : l.shift(); + }); +}; +``` + +```js +mergeSort([5, 1, 4, 2, 3]); // [1, 2, 3, 4, 5] +``` From cba3aa675577c2aceaea2846dfa245ccd980d578 Mon Sep 17 00:00:00 2001 From: Isabelle Viktoria Maciohsek Date: Sun, 27 Dec 2020 22:55:37 +0200 Subject: [PATCH 06/28] Add mergeSortedArrays --- snippets/mergeSortedArrays.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 snippets/mergeSortedArrays.md diff --git a/snippets/mergeSortedArrays.md b/snippets/mergeSortedArrays.md new file mode 100644 index 000000000..fb23232c1 --- /dev/null +++ b/snippets/mergeSortedArrays.md @@ -0,0 +1,26 @@ +--- +title: mergeSortedArrays +tags: array,intermediate +--- + +Merges two sorted arrays into one. + +- Use the spread operator (`...`) to clone both of the given arrays. +- Use `Array.from()` to create an array of the appropriate length based on the given arrays. +- Use `Array.prototype.shift()` to populate the newly created array from the removed elements of the cloned arrays. + +```js +const mergeSortedArrays = (a, b) => { + const _a = [...a], + _b = [...b]; + return Array.from({ length: _a.length + _b.length }, () => { + if (!_a.length) return _b.shift(); + else if (!_b.length) return _a.shift(); + else return _a[0] > _b[0] ? _b.shift() : _a.shift(); + }); +}; +``` + +```js +mergeSortedArrays([1, 4, 5], [2, 3, 6]); // [1, 2, 3, 4, 5, 6] +``` From 40c919330e8f6b09934e770af093dd9691438beb Mon Sep 17 00:00:00 2001 From: Isabelle Viktoria Maciohsek Date: Mon, 28 Dec 2020 12:07:53 +0200 Subject: [PATCH 07/28] Add linearSearch --- snippets/linearSearch.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 snippets/linearSearch.md diff --git a/snippets/linearSearch.md b/snippets/linearSearch.md new file mode 100644 index 000000000..91143c366 --- /dev/null +++ b/snippets/linearSearch.md @@ -0,0 +1,25 @@ +--- +title: linearSearch +tags: algorithm,array,beginner +--- + +Finds the first index of a given element in an array using the linear search algorithm. + +- Use a `for...in` loop to iterate over the indexes of the given array. +- Check if the element in the corresponding index is equal to `item`. +- If the element is found, return the index, using the unary `+` operator to convert it from a string to a number. +- If the element is not found after iterating over the whole array, return `-1`. + +```js +const linearSearch = (arr, item) => { + for (const i in arr) { + if (arr[i] === item) return +i; + } + return -1; +}; +``` + +```js +linearSearch([2, 9, 9], 9); // 1 +linearSearch([2, 9, 9], 7); // -1 +``` From 720d7a8f1ccbfd716d33b91d50b8e2eb437f97a9 Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Mon, 28 Dec 2020 12:35:44 +0200 Subject: [PATCH 08/28] Add binarySearech --- snippets/binarySearch.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 snippets/binarySearch.md diff --git a/snippets/binarySearch.md b/snippets/binarySearch.md new file mode 100644 index 000000000..55541ebe8 --- /dev/null +++ b/snippets/binarySearch.md @@ -0,0 +1,35 @@ +--- +title: binarySearch +tags: algorithm,array,beginner +--- + +Finds the index of a given element in a sorted array using the binary search algorithm. + +- Declare the left and right search boundaries, `l` and `r`, initialized to `0` and the `length` of the array respectively. +- Use a `while` loop to repeatedly narrow down the search subarray, using `Math.floor()` to cut it in half. +- Return the index of the element if found, otherwise return `-1`. +- **Note:** Does not account for duplicate values in the array. + +```js +const binarySearch = (arr, item) => { + let l = 0, + r = arr.length - 1; + + while (l <= r) { + const mid = Math.floor((l + r) / 2); + const guess = arr[mid]; + if (guess === item) return mid; + + if (guess > item) r = mid - 1; + else l = mid + 1; + } + + return -1; +}; +``` + +```js +binarySearch([1, 2, 3, 4, 5], 1); // 0 +binarySearch([1, 2, 3, 4, 5], 5); // 4 +binarySearch([1, 2, 3, 4, 5], 6); // -1 +``` From 414e374ab40b148365d733017305f0aca28701aa Mon Sep 17 00:00:00 2001 From: Isabelle Viktoria Maciohsek Date: Mon, 28 Dec 2020 13:11:01 +0200 Subject: [PATCH 09/28] Add primeFactors --- snippets/primeFactors.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 snippets/primeFactors.md diff --git a/snippets/primeFactors.md b/snippets/primeFactors.md new file mode 100644 index 000000000..959db4d85 --- /dev/null +++ b/snippets/primeFactors.md @@ -0,0 +1,29 @@ +--- +title: primeFactors +tags: math,algorithm,beginner +--- + +Finds the prime factors of a given number using the trial division algorithm. + +- Use a `while` loop to iterate over all possible prime factors, starting with `2`. +- If the current factor, `f`, exactly divides `n`, add `f` to the factors array and divide `n` by `f`. Otherwise, increment `f` by one. + +```js +const primeFactors = n => { + let a = [], + f = 2; + while (n > 1) { + if (n % f === 0) { + a.push(f); + n /= f; + } else { + f++; + } + } + return a; +}; +``` + +```js +primeFactors(147); // [3, 7, 7] +``` From 487884e09467dfb98e0b4ca7043069698b62a16b Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Mon, 28 Dec 2020 13:41:19 +0200 Subject: [PATCH 10/28] Add euclideanDistance --- snippets/euclideanDistance.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 snippets/euclideanDistance.md diff --git a/snippets/euclideanDistance.md b/snippets/euclideanDistance.md new file mode 100644 index 000000000..5ce5a39bc --- /dev/null +++ b/snippets/euclideanDistance.md @@ -0,0 +1,19 @@ +--- +title: euclideanDistance +tags: math,algorithm,intermediate +--- + +Calculates the distance between two points in any number of dimensions. + +- Use `Object.keys()` and `Array.prototype.map()` to map each coordinate to its difference between the two points. +- Use `Math.hypot()` to calculate the Euclidean distance between the two points. + +```js +const euclideanDistance = (a, b) => + Math.hypot(...Object.keys(a).map(k => b[k] - a[k])); +``` + +```js +euclideanDistance([1, 1], [2, 3]); // ~2.2361 +euclideanDistance([1, 1, 1], [2, 3, 2]); // ~2.4495 +``` From f1e7ea511618ae749db78b055daf3b570bac34e6 Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Mon, 28 Dec 2020 13:49:24 +0200 Subject: [PATCH 11/28] Tag algorithmic snippets --- snippets/arithmeticProgression.md | 4 ++-- snippets/binomialCoefficient.md | 2 +- snippets/distance.md | 2 +- snippets/factorial.md | 2 +- snippets/fibonacci.md | 2 +- snippets/gcd.md | 2 +- snippets/geometricProgression.md | 2 +- snippets/hammingDistance.md | 2 +- snippets/isPrime.md | 2 +- snippets/lcm.md | 2 +- snippets/luhnCheck.md | 2 +- snippets/permutations.md | 2 +- snippets/powerset.md | 2 +- snippets/primes.md | 2 +- snippets/vectorDistance.md | 2 +- 15 files changed, 16 insertions(+), 16 deletions(-) diff --git a/snippets/arithmeticProgression.md b/snippets/arithmeticProgression.md index aab41ce2f..6ac182b3f 100644 --- a/snippets/arithmeticProgression.md +++ b/snippets/arithmeticProgression.md @@ -1,6 +1,6 @@ --- title: arithmeticProgression -tags: math,beginner +tags: math,algorithm,beginner --- Creates an array of numbers in the arithmetic progression, starting with the given positive integer and up to the specified limit. @@ -8,7 +8,7 @@ Creates an array of numbers in the arithmetic progression, starting with the giv - Use `Array.from()` to create an array of the desired length, `lim/n`, and a map function to fill it with the desired values in the given range. ```js -const arithmeticProgression = (n, lim) => +const arithmeticProgression = (n, lim) => Array.from({ length: Math.ceil(lim / n) }, (_, i) => (i + 1) * n ); ``` diff --git a/snippets/binomialCoefficient.md b/snippets/binomialCoefficient.md index 3e0267ea2..791283296 100644 --- a/snippets/binomialCoefficient.md +++ b/snippets/binomialCoefficient.md @@ -1,6 +1,6 @@ --- title: binomialCoefficient -tags: math,beginner +tags: math,algorithm,beginner --- Calculates the number of ways to choose `k` items from `n` items without repetition and without order. diff --git a/snippets/distance.md b/snippets/distance.md index 6bf24f641..bc375a64e 100644 --- a/snippets/distance.md +++ b/snippets/distance.md @@ -1,6 +1,6 @@ --- title: distance -tags: math,beginner +tags: math,algorithm,beginner --- Calculates the distance between two points. diff --git a/snippets/factorial.md b/snippets/factorial.md index 2c6eb1acb..cddd9f499 100644 --- a/snippets/factorial.md +++ b/snippets/factorial.md @@ -1,6 +1,6 @@ --- title: factorial -tags: math,recursion,beginner +tags: math,algorithm,recursion,beginner --- Calculates the factorial of a number. diff --git a/snippets/fibonacci.md b/snippets/fibonacci.md index 37df66289..c761e9c5b 100644 --- a/snippets/fibonacci.md +++ b/snippets/fibonacci.md @@ -1,6 +1,6 @@ --- title: fibonacci -tags: math,intermediate +tags: math,algorithm,intermediate --- Generates an array, containing the Fibonacci sequence, up until the nth term. diff --git a/snippets/gcd.md b/snippets/gcd.md index b662823e6..b262f7221 100644 --- a/snippets/gcd.md +++ b/snippets/gcd.md @@ -1,6 +1,6 @@ --- title: gcd -tags: math,recursion,beginner +tags: math,algorithm,recursion,beginner --- Calculates the greatest common divisor between two or more numbers/arrays. diff --git a/snippets/geometricProgression.md b/snippets/geometricProgression.md index 40a7b7c47..cdd3a6f35 100644 --- a/snippets/geometricProgression.md +++ b/snippets/geometricProgression.md @@ -1,6 +1,6 @@ --- title: geometricProgression -tags: math,intermediate +tags: math,algorithm,intermediate --- Initializes an array containing the numbers in the specified range where `start` and `end` are inclusive and the ratio between two terms is `step`. diff --git a/snippets/hammingDistance.md b/snippets/hammingDistance.md index 51530ad35..24b30f65b 100644 --- a/snippets/hammingDistance.md +++ b/snippets/hammingDistance.md @@ -1,6 +1,6 @@ --- title: hammingDistance -tags: math,intermediate +tags: math,algorithm,intermediate --- Calculates the Hamming distance between two values. diff --git a/snippets/isPrime.md b/snippets/isPrime.md index 52f56c8ca..6aa2a231e 100644 --- a/snippets/isPrime.md +++ b/snippets/isPrime.md @@ -1,6 +1,6 @@ --- title: isPrime -tags: math,beginner +tags: math,algorithm,beginner --- Checks if the provided integer is a prime number. diff --git a/snippets/lcm.md b/snippets/lcm.md index 2e63fbe1b..66667a8c0 100644 --- a/snippets/lcm.md +++ b/snippets/lcm.md @@ -1,6 +1,6 @@ --- title: lcm -tags: math,recursion,intermediate +tags: math,algorithm,recursion,intermediate --- Calculates the least common multiple of two or more numbers. diff --git a/snippets/luhnCheck.md b/snippets/luhnCheck.md index 42bf9f318..fa842f1da 100644 --- a/snippets/luhnCheck.md +++ b/snippets/luhnCheck.md @@ -1,6 +1,6 @@ --- title: luhnCheck -tags: math,advanced +tags: math,algorithm,advanced --- Implementation of the [Luhn Algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm) used to validate a variety of identification numbers, such as credit card numbers, IMEI numbers, National Provider Identifier numbers etc. diff --git a/snippets/permutations.md b/snippets/permutations.md index 1c10d8782..8e94d7b5b 100644 --- a/snippets/permutations.md +++ b/snippets/permutations.md @@ -1,6 +1,6 @@ --- title: permutations -tags: array,recursion,advanced +tags: array,algorithm,recursion,advanced --- Generates all permutations of an array's elements (contains duplicates). diff --git a/snippets/powerset.md b/snippets/powerset.md index 823c60ab4..973f4dadb 100644 --- a/snippets/powerset.md +++ b/snippets/powerset.md @@ -1,6 +1,6 @@ --- title: powerset -tags: math,beginner +tags: math,algorithm,beginner --- Returns the powerset of a given array of numbers. diff --git a/snippets/primes.md b/snippets/primes.md index 0f21b1c48..303ffeaab 100644 --- a/snippets/primes.md +++ b/snippets/primes.md @@ -1,6 +1,6 @@ --- title: primes -tags: math,intermediate +tags: math,algorithm,intermediate --- Generates primes up to a given number, using the Sieve of Eratosthenes. diff --git a/snippets/vectorDistance.md b/snippets/vectorDistance.md index df660c9f5..8daf94d6f 100644 --- a/snippets/vectorDistance.md +++ b/snippets/vectorDistance.md @@ -1,6 +1,6 @@ --- title: vectorDistance -tags: math,beginner +tags: math,algorithm,beginner --- Calculates the distance between two vectors. From 4c7b5303646930fd6230593a19a9d4287dc40320 Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Mon, 28 Dec 2020 15:38:40 +0200 Subject: [PATCH 12/28] Add kMeans --- snippets/kMeans.md | 60 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 snippets/kMeans.md diff --git a/snippets/kMeans.md b/snippets/kMeans.md new file mode 100644 index 000000000..72b727b95 --- /dev/null +++ b/snippets/kMeans.md @@ -0,0 +1,60 @@ +--- +title: kMeans +tags: algorithm,array,advanced +--- + +Groups the given data into `k` clusters using the k-means clustering algorithm. + +- Use `Array.from()` and `Array.prototype.slice()` to initialize appropriate variables for the cluster `centroids`, `distances` and `classes`. +- Use a `while` loop to repeat the assignment and update steps as long as there are changes in the previous iteration, as indicated by `itr`. +- Calculate the euclidean distance between each data point and centroid using `Math.hypot()`, `Object.keys()` and `Array.prototype.map()`. +- Use `Array.prototype.indexOf()` and `Math.min()` to find the closest centroid. +- Use `Array.from()` and `Array.prototype.reduce()`, as well as `parseFloat()` and `Number.prototype.toFixed()` to calculate the new centroids. + +```js +const kMeans = (data, k = 1) => { + const centroids = data.slice(0, k); + const distances = Array.from({ length: data.length }, () => + Array.from({ length: k }, () => 0) + ); + const classes = Array.from({ length: data.length }, () => -1); + + let itr = true; + while (itr) { + itr = false; + + for (let d in data) { + for (let c = 0; c < k; c++) { + distances[d][c] = Math.hypot( + ...Object.keys(data[0]).map(key => data[d][key] - centroids[c][key]) + ); + } + + const m = distances[d].indexOf(Math.min(...distances[d])); + if (classes[d] !== m) itr = true; + classes[d] = m; + } + + for (let c = 0; c < k; c++) { + centroids[c] = Array.from({ length: data[0].length }, () => 0); + const size = data.reduce((acc, _, d) => { + if (classes[d] === c) { + acc++; + for (let i in data[0]) centroids[c][i] += data[d][i]; + } + return acc; + }, 0); + + for (let i in data[0]) { + centroids[c][i] = parseFloat(Number(centroids[c][i] / size).toFixed(2)); + } + } + } + + return classes; +}; +``` + +```js +kMeans([[0, 0], [0, 1], [1, 3], [2, 0]], 2); // [0, 1, 1, 0] +``` From ebfc68e2215f90b3f330fca819bafcee68c11af7 Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Mon, 28 Dec 2020 16:31:43 +0200 Subject: [PATCH 13/28] Add kNearestNeighbors --- snippets/kNearestNeighbors.md | 49 +++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 snippets/kNearestNeighbors.md diff --git a/snippets/kNearestNeighbors.md b/snippets/kNearestNeighbors.md new file mode 100644 index 000000000..5924f2249 --- /dev/null +++ b/snippets/kNearestNeighbors.md @@ -0,0 +1,49 @@ +--- +title: kNearestNeighbors +tags: algorithm,array,advanced +--- + +Classifies a data point relative to a labelled data set using the k-nearest neighbors algorithm. + +- Use `Array.prototype.map()` to map the `data` to objects containing the euclidean distance of each element from `point`, calculated using `Math.hypot()`, `Object.keys()` and its `label`. +- Use `Array.prototype.sort()` and `Array.prototype.slice()` to get the `k` nearest neighbors of `point`. +- Use `Array.prototype.reduce()` in combination with `Object.keys()` and `Array.prototype.indexOf()` to find the most frequent `label` among them. + +```js +const kNearestNeighbors = (data, labels, point, k = 3) => { + const kNearest = data + .map((el, i) => ({ + dist: Math.hypot(...Object.keys(el).map(key => point[key] - el[key])), + label: labels[i] + })) + .sort((a, b) => a.dist - b.dist) + .slice(0, k); + + return kNearest.reduce( + (acc, { label }, i) => { + acc.classCounts[label] = + Object.keys(acc.classCounts).indexOf(label) !== -1 + ? acc.classCounts[label] + 1 + : 1; + if (acc.classCounts[label] > acc.topClassCount) { + acc.topClassCount = acc.classCounts[label]; + acc.topClass = label; + } + return acc; + }, + { + classCounts: {}, + topClass: kNearest[0].label, + topClassCount: 0 + } + ).topClass; +}; +``` + +```js +const data = [[0, 0], [0, 1], [1, 3], [2, 0]]; +const labels = [0, 1, 1, 0]; + +kNearestNeighbors(data, labels, [1, 2], 2); // 1 +kNearestNeighbors(data, labels, [1, 0], 2); // 0 +``` From 33f3c8c83c16f9a6df4cc6876c23cf08a5226787 Mon Sep 17 00:00:00 2001 From: Isabelle Viktoria Maciohsek Date: Mon, 28 Dec 2020 20:10:18 +0200 Subject: [PATCH 14/28] Add caesarCipher --- snippets/caesarCipher.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 snippets/caesarCipher.md diff --git a/snippets/caesarCipher.md b/snippets/caesarCipher.md new file mode 100644 index 000000000..2a8e9397e --- /dev/null +++ b/snippets/caesarCipher.md @@ -0,0 +1,34 @@ +--- +title: caesarCipher +tags: algorithm,string,beginner +--- + +Encrypts or decrypts a given string using the Caesar cipher. + +- Use the modulo (`%`) operator and the ternary operator (`?`) to calculate the correct encryption/decryption key. +- Use the spread operator (`...`) and `Array.prototype.map()` to iterate over the letters of the given string. +- Use `String.prototype.charCodeAt()` and `String.fromCharCode()` to convert each letter appropriately, ignoring special characters, spaces et.c +- Use `Array.prototype.join()` to combine all the letters into a string. +- Pass `true` to the last parameter, `decrypt`, to decrypt an encrypted string. + +```js +const caesarCipher = (str, shift, decrypt = false) => { + const s = decrypt ? (26 - shift) % 26 : shift; + const n = s > 0 ? s : 26 + (s % 26); + return [...str] + .map((l, i) => { + const c = str.charCodeAt(i); + if (c >= 65 && c <= 90) + return String.fromCharCode(((c - 65 + n) % 26) + 65); + if (c >= 97 && c <= 122) + return String.fromCharCode(((c - 97 + n) % 26) + 97); + return l; + }) + .join(''); +}; +``` + +```js +caesarCipher('Hello World!', -3); // 'Ebiil Tloia!' +caesarCipher('Ebiil Tloia!', 23, true); // 'Hello World!' +``` From dfd3ebd398b42208c4ce492b377bd83133ed647b Mon Sep 17 00:00:00 2001 From: Isabelle Viktoria Maciohsek Date: Mon, 28 Dec 2020 20:23:47 +0200 Subject: [PATCH 15/28] Add cartesianProduct --- snippets/cartesianProduct.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 snippets/cartesianProduct.md diff --git a/snippets/cartesianProduct.md b/snippets/cartesianProduct.md new file mode 100644 index 000000000..2d9da3691 --- /dev/null +++ b/snippets/cartesianProduct.md @@ -0,0 +1,18 @@ +--- +title: cartesianProduct +tags: array,beginner +--- + +Calculates the cartesian product of two arrays. + +- Use `Array.prototype.reduce()`, `Array.prototype.map()` and the spread operator (`...`) to generate all possible element pairs from the two arrays. + +```js +const cartesianProduct = (a, b) => + a.reduce((p, x) => [...p, ...b.map(y => [x, y])], []); +``` + +```js +cartesianProduct(['x', 'y'], [1, 2]); +// [['x', 1], ['x', 2], ['y', 1], ['y', 2]] +``` From d93e725f1f23fa06d4bab412e76eead6afb0b5a2 Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Mon, 28 Dec 2020 21:53:53 +0200 Subject: [PATCH 16/28] Add insertionSort --- snippets/insertionSort.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 snippets/insertionSort.md diff --git a/snippets/insertionSort.md b/snippets/insertionSort.md new file mode 100644 index 000000000..4f5f78110 --- /dev/null +++ b/snippets/insertionSort.md @@ -0,0 +1,34 @@ +--- +title: insertionSort +tags: algorithm,array,intermediate +--- + +Sorts an array of numbers, using the insertion sort algorithm. + +- Use `Array.prototype.reduce()` to iterate over all the elements in the given array. +- If the `length` of the accumulator is `0`, add the current element to it. +- Use `Array.prototype.some()` to iterate over the results in the accumulator until the correct position is found. +- Use `Array.prototype.splice()` to insert the current element into the accumulator. + +```js +const insertionSort = arr => + arr.reduce((acc, x) => { + if (!acc.length) return [x]; + acc.some((y, j) => { + if (x <= y) { + acc.splice(j, 0, x); + return true; + } + if (x > y && j === acc.length - 1) { + acc.splice(j + 1, 0, x); + return true; + } + return false; + }); + return acc; + }, []); +``` + +```js +insertionSort([6, 3, 4, 1]); // [1, 3, 4, 6] +``` From fe800d4e028c24e8614045357b0ee793deb9ef92 Mon Sep 17 00:00:00 2001 From: Isabelle Viktoria Maciohsek Date: Mon, 28 Dec 2020 22:11:56 +0200 Subject: [PATCH 17/28] Add bucketSort --- snippets/bucketSort.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 snippets/bucketSort.md diff --git a/snippets/bucketSort.md b/snippets/bucketSort.md new file mode 100644 index 000000000..56cde5756 --- /dev/null +++ b/snippets/bucketSort.md @@ -0,0 +1,32 @@ +--- +title: bucketSort +tags: algorithm,array,intermediate +--- + +Sorts an array of numbers, using the bucket sort algorithm. + +- Use `Math.min(),` `Math.max()` and the spread operator (`...`) to find the minimum and maximum values of the given array. +- Use `Array.from()` and `Math.floor()` to create the appropriate number of `buckets` (empty arrays). +- Use `Array.prototype.forEach()` to populate each bucket with the appropriate elements from the array. +- Use `Array.prototype.reduce()`, the spread operator (`...`) and `Array.prototype.sort()` to sort each bucket and append it to the result. + +```js +const bucketSort = (arr, size = 5) => { + const min = Math.min(...arr); + const max = Math.max(...arr); + const buckets = Array.from( + { length: Math.floor((max - min) / size) + 1 }, + () => [] + ); + + arr.forEach(val => { + buckets[Math.floor((val - min) / size)].push(val); + }); + + return buckets.reduce((acc, b) => [...acc, ...b.sort((a, b) => a - b)], []); +}; +``` + +```js +bucketSort([6, 3, 4, 1]); // [1, 3, 4, 6] +``` From 3d6dc4bf400c5ec856888c206d49279bfd666108 Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Mon, 28 Dec 2020 22:48:09 +0200 Subject: [PATCH 18/28] Add heapsort --- snippets/heapsort.md | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 snippets/heapsort.md diff --git a/snippets/heapsort.md b/snippets/heapsort.md new file mode 100644 index 000000000..16c87592e --- /dev/null +++ b/snippets/heapsort.md @@ -0,0 +1,43 @@ +--- +title: heapsort +tags: algorithm,array,recursion,advanced +--- + +Sorts an array of numbers, using the heapsort algorithm. + +- Use recursion. +- Use the spread operator (`...`) to clone the original array, `arr`. +- Use closures to declare a variable, `l`, and a function `heapify`. +- Use a `for` loop and `Math.floor()` in combination with `heapify` to create a max heap from the array. +- Use a `for` loop to repeatedly narrow down the considered range, using `heapify` and swapping values as necessary in order to sort the cloned array. + +```js +const heapsort = arr => { + const a = [...arr]; + let l = a.length; + + const heapify = (a, i) => { + const left = 2 * i + 1; + const right = 2 * i + 2; + let max = i; + if (left < l && a[left] > a[max]) max = left; + if (right < l && a[right] > a[max]) max = right; + if (max !== i) { + [a[max], a[i]] = [a[i], a[max]]; + heapify(a, max); + } + }; + + for (let i = Math.floor(l / 2); i >= 0; i -= 1) heapify(a, i); + for (i = a.length - 1; i > 0; i--) { + [a[0], a[i]] = [a[i], a[0]]; + l--; + heapify(a, 0); + } + return a; +}; +``` + +```js +heapsort([6, 3, 4, 1]); // [1, 3, 4, 6] +``` From 443b97a4caeb88d92899ffe49123cda489e06749 Mon Sep 17 00:00:00 2001 From: Isabelle Viktoria Maciohsek Date: Tue, 29 Dec 2020 12:18:58 +0200 Subject: [PATCH 19/28] Update bubbleSort.md --- snippets/bubbleSort.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/snippets/bubbleSort.md b/snippets/bubbleSort.md index 8e0396284..c3126a3a0 100644 --- a/snippets/bubbleSort.md +++ b/snippets/bubbleSort.md @@ -14,24 +14,17 @@ Sorts an array of numbers, using the bubble sort algorithm. ```js const bubbleSort = arr => { let swapped = false; - const a = [...arr]; - for (let i = 1; i < a.length - 1; i++) { swapped = false; - for (let j = 0; j < a.length - i; j++) { if (a[j + 1] < a[j]) { [a[j], a[j + 1]] = [a[j + 1], a[j]]; swapped = true; } } - - if (!swapped) { - return a; - } + if (!swapped) return a; } - return a; }; ``` From b8f032cc289b662ab72ec18086249bec3d72dc79 Mon Sep 17 00:00:00 2001 From: Isabelle Viktoria Maciohsek Date: Tue, 29 Dec 2020 12:22:44 +0200 Subject: [PATCH 20/28] Update bucketSort.md --- snippets/bucketSort.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/snippets/bucketSort.md b/snippets/bucketSort.md index 56cde5756..8cb8471f5 100644 --- a/snippets/bucketSort.md +++ b/snippets/bucketSort.md @@ -18,11 +18,9 @@ const bucketSort = (arr, size = 5) => { { length: Math.floor((max - min) / size) + 1 }, () => [] ); - arr.forEach(val => { buckets[Math.floor((val - min) / size)].push(val); }); - return buckets.reduce((acc, b) => [...acc, ...b.sort((a, b) => a - b)], []); }; ``` From c6cc0cb2b7d3892758541a0a186be61794177ab0 Mon Sep 17 00:00:00 2001 From: Isabelle Viktoria Maciohsek Date: Tue, 29 Dec 2020 12:29:21 +0200 Subject: [PATCH 21/28] Update caesarCipher.md --- snippets/caesarCipher.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/caesarCipher.md b/snippets/caesarCipher.md index 2a8e9397e..42f65225d 100644 --- a/snippets/caesarCipher.md +++ b/snippets/caesarCipher.md @@ -7,7 +7,7 @@ Encrypts or decrypts a given string using the Caesar cipher. - Use the modulo (`%`) operator and the ternary operator (`?`) to calculate the correct encryption/decryption key. - Use the spread operator (`...`) and `Array.prototype.map()` to iterate over the letters of the given string. -- Use `String.prototype.charCodeAt()` and `String.fromCharCode()` to convert each letter appropriately, ignoring special characters, spaces et.c +- Use `String.prototype.charCodeAt()` and `String.fromCharCode()` to convert each letter appropriately, ignoring special characters, spaces etc. - Use `Array.prototype.join()` to combine all the letters into a string. - Pass `true` to the last parameter, `decrypt`, to decrypt an encrypted string. From 2ddddfe7947587203c7408ffaf6438a9891b6f22 Mon Sep 17 00:00:00 2001 From: Isabelle Viktoria Maciohsek Date: Tue, 29 Dec 2020 12:31:43 +0200 Subject: [PATCH 22/28] Update cartesianProduct.md --- snippets/cartesianProduct.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/cartesianProduct.md b/snippets/cartesianProduct.md index 2d9da3691..5c80b8bea 100644 --- a/snippets/cartesianProduct.md +++ b/snippets/cartesianProduct.md @@ -1,6 +1,6 @@ --- title: cartesianProduct -tags: array,beginner +tags: math,array,beginner --- Calculates the cartesian product of two arrays. From 856703a41f229d8d645b3c05da128f3cb01d2989 Mon Sep 17 00:00:00 2001 From: Isabelle Viktoria Maciohsek Date: Tue, 29 Dec 2020 12:36:50 +0200 Subject: [PATCH 23/28] Update gcd.md --- snippets/gcd.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/gcd.md b/snippets/gcd.md index b262f7221..ba2f2d7c0 100644 --- a/snippets/gcd.md +++ b/snippets/gcd.md @@ -1,6 +1,6 @@ --- title: gcd -tags: math,algorithm,recursion,beginner +tags: math,algorithm,recursion,intermediate --- Calculates the greatest common divisor between two or more numbers/arrays. From 31faa2ee2b8eecee87ddfab743ee0c805b635b9b Mon Sep 17 00:00:00 2001 From: Isabelle Viktoria Maciohsek Date: Tue, 29 Dec 2020 12:48:04 +0200 Subject: [PATCH 24/28] Update kMeans.md --- snippets/kMeans.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/snippets/kMeans.md b/snippets/kMeans.md index 72b727b95..3d622009a 100644 --- a/snippets/kMeans.md +++ b/snippets/kMeans.md @@ -18,8 +18,8 @@ const kMeans = (data, k = 1) => { Array.from({ length: k }, () => 0) ); const classes = Array.from({ length: data.length }, () => -1); - let itr = true; + while (itr) { itr = false; @@ -29,7 +29,6 @@ const kMeans = (data, k = 1) => { ...Object.keys(data[0]).map(key => data[d][key] - centroids[c][key]) ); } - const m = distances[d].indexOf(Math.min(...distances[d])); if (classes[d] !== m) itr = true; classes[d] = m; @@ -44,7 +43,6 @@ const kMeans = (data, k = 1) => { } return acc; }, 0); - for (let i in data[0]) { centroids[c][i] = parseFloat(Number(centroids[c][i] / size).toFixed(2)); } From 8e0ff8babc94ef8b6190e0b2955b096d169b6ed1 Mon Sep 17 00:00:00 2001 From: Isabelle Viktoria Maciohsek Date: Tue, 29 Dec 2020 12:56:07 +0200 Subject: [PATCH 25/28] Update levenshteinDistance.md --- snippets/levenshteinDistance.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/snippets/levenshteinDistance.md b/snippets/levenshteinDistance.md index ad33293ef..e4c9bc22c 100644 --- a/snippets/levenshteinDistance.md +++ b/snippets/levenshteinDistance.md @@ -15,9 +15,7 @@ Calculates the difference between two strings. const levenshteinDistance = (s, t) => { if (!s.length) return t.length; if (!t.length) return s.length; - const arr = []; - for (let i = 0; i <= t.length; i++) { arr[i] = [i]; for (let j = 1; j <= s.length; j++) { @@ -31,7 +29,6 @@ const levenshteinDistance = (s, t) => { ); } } - return arr[t.length][s.length]; }; ``` From 3b4f458782c456f0629ff2fbe5c7b411afd2e6a7 Mon Sep 17 00:00:00 2001 From: Isabelle Viktoria Maciohsek Date: Tue, 29 Dec 2020 13:03:18 +0200 Subject: [PATCH 26/28] Update quickSort.md --- snippets/quickSort.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/snippets/quickSort.md b/snippets/quickSort.md index c6dc6c4fe..fe419e5a9 100644 --- a/snippets/quickSort.md +++ b/snippets/quickSort.md @@ -15,9 +15,7 @@ Sorts an array of numbers, using the quicksort algorithm. ```js const quickSort = arr => { const a = [...arr]; - if (a.length < 2) return a; - const pivotIndex = Math.floor(arr.length / 2); const pivot = a[pivotIndex]; const [lo, hi] = a.reduce( @@ -31,7 +29,6 @@ const quickSort = arr => { }, [[], []] ); - return [...quickSort(lo), pivot, ...quickSort(hi)]; }; ``` From 3e1e38338682ad3007b9b6abfd3f861d7ecd9f7c Mon Sep 17 00:00:00 2001 From: Isabelle Viktoria Maciohsek Date: Tue, 29 Dec 2020 13:04:24 +0200 Subject: [PATCH 27/28] Update selectionSort.md --- snippets/selectionSort.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/snippets/selectionSort.md b/snippets/selectionSort.md index 1ac735fc8..3fcd2d0ce 100644 --- a/snippets/selectionSort.md +++ b/snippets/selectionSort.md @@ -12,14 +12,12 @@ Sorts an array of numbers, using the selection sort algorithm. ```js const selectionSort = arr => { const a = [...arr]; - for (let i = 0; i < a.length; i++) { const min = a .slice(i + 1) .reduce((acc, val, j) => (val < a[acc] ? j + i + 1 : acc), i); if (min !== i) [a[i], a[min]] = [a[min], a[i]]; } - return a; }; ``` From 663fb78277ff60432a23cd18432b54c3c5f34915 Mon Sep 17 00:00:00 2001 From: Isabelle Viktoria Maciohsek Date: Tue, 29 Dec 2020 13:06:47 +0200 Subject: [PATCH 28/28] Update binarySearch.md --- snippets/binarySearch.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/snippets/binarySearch.md b/snippets/binarySearch.md index 55541ebe8..deef65478 100644 --- a/snippets/binarySearch.md +++ b/snippets/binarySearch.md @@ -14,16 +14,13 @@ Finds the index of a given element in a sorted array using the binary search alg const binarySearch = (arr, item) => { let l = 0, r = arr.length - 1; - while (l <= r) { const mid = Math.floor((l + r) / 2); const guess = arr[mid]; if (guess === item) return mid; - if (guess > item) r = mid - 1; else l = mid + 1; } - return -1; }; ```