├── .gitignore ├── tsconfig.json ├── lib ├── protos │ ├── Arrays.d.ts │ └── Arrays.js ├── index.d.ts ├── sArray.d.ts ├── index.js └── sArray.js ├── README.md ├── package.json ├── LICENSE └── src ├── protos ├── proto.ts └── Arrays.ts ├── index.ts └── sArray.ts /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules 3 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "outDir": "lib" 5 | }, 6 | "include": [ 7 | "src" 8 | ] 9 | } -------------------------------------------------------------------------------- /lib/protos/Arrays.d.ts: -------------------------------------------------------------------------------- 1 | declare module ArrayHelpers { 2 | /** 3 | * Partition for quick sort 4 | */ 5 | function partition(array: number[], start: number, before: number): void; 6 | /** Merge (conquer) step of mergeSort */ 7 | function merge(left: number[], right: number[]): number[]; 8 | } 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Algorithms 2 | 3 | # Install 4 | 5 | ``` 6 | npm install algos-ts 7 | ``` 8 | 9 | # WIP 10 | ** this is a work in progress. Stuff will change, but you can already use it and chat with me ** 11 | 12 | ## Use 13 | _import the function you need and use it. that's it!_ 14 | 15 | 16 | ``` 17 | import {bubbleSort, quickSort, insertionSort, mergeSort, binarySearch} from 'algos-ts'; 18 | 19 | const mergeSorted = mergeSort([1,6,123,456,123,43]); 20 | ``` 21 | 22 | 23 | _Made with :heart: in London_ 24 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "algos-ts", 3 | "version": "1.0.3", 4 | "description": "algorithms done right in typescript ", 5 | "main": "lib/index", 6 | "typings": "lib/index", 7 | "scripts": { 8 | "build": "tsc -p .", 9 | "publish": "npm run build && npm version patch && npm publish" 10 | }, 11 | "keywords": [ 12 | "typescript", 13 | "algorithms" 14 | ], 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/gp187/algos-ts" 18 | }, 19 | "author": "Gabri3l", 20 | "license": "ISC", 21 | "devDependencies": { 22 | "typescript": "^2.4.2" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/index.d.ts: -------------------------------------------------------------------------------- 1 | export declare function bubbleSort(array: number[]): number[]; 2 | /** 3 | * Sorts an array using quick sort 4 | */ 5 | export declare function quickSort(array: number[]): number[]; 6 | /** 7 | * Sorts an array using insertion sort 8 | */ 9 | export declare function insertionSort(array: number[]): number[]; 10 | /** 11 | * Sorts an array using merge sort 12 | */ 13 | export declare function mergeSort(array: number[]): number[]; 14 | /** 15 | * Searches for specific element in a given sorted array 16 | * @returns the index of the element (-1 if its not found) 17 | */ 18 | export declare function binarySearch(array: number[], element: number, start?: number, end?: number): number; 19 | -------------------------------------------------------------------------------- /lib/sArray.d.ts: -------------------------------------------------------------------------------- 1 | export declare function bubbleSort(array: number[]): number[]; 2 | /** 3 | * Sorts an array using quick sort 4 | */ 5 | export declare function quickSort(array: number[]): number[]; 6 | /** 7 | * Sorts an array using insertion sort 8 | */ 9 | export declare function insertionSort(array: number[]): number[]; 10 | /** 11 | * Sorts an array using merge sort 12 | */ 13 | export declare function mergeSort(array: number[]): number[]; 14 | /** 15 | * Searches for specific element in a given sorted array 16 | * @returns the index of the element (-1 if its not found) 17 | */ 18 | export declare function binarySearch(array: number[], element: number, start?: number, end?: number): number; 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Gabriel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/protos/proto.ts: -------------------------------------------------------------------------------- 1 | declare global { 2 | interface Array { 3 | /** 4 | * Check if all the variables in the array are truthy 5 | * @returns {boolean} 6 | */ 7 | isAllTrue(): boolean; 8 | /** 9 | * Sort with correct ordering 10 | */ 11 | sort(compareFn?: (a: T, b: T) => number): this; 12 | /** 13 | * Sort array by key 14 | */ 15 | sortBy(param: string): this; 16 | /** 17 | * Bubble sort 18 | */ 19 | bubbleSort(): number[]; 20 | /** 21 | * Quick sort 22 | */ 23 | quickSort(): number[]; 24 | /** 25 | * Insert sort 26 | */ 27 | insertionSort(): number[]; 28 | /** 29 | * Merge sort algo 30 | */ 31 | mergeSort(): number[]; 32 | /** 33 | * Binary search 34 | */ 35 | binarySearch(element: number, start: number, end: number): number 36 | /** 37 | * Find repeated item 38 | */ 39 | firstRepeatedItem(): T; 40 | } 41 | } 42 | import './Arrays'; -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | export function bubbleSort(array: number[]): number[] { 4 | array = array.slice(); 5 | while (true) { 6 | let swapped = false; 7 | for (let j = 0; j < array.length - 1; j++) { 8 | if (array[j] > array[j + 1]) { 9 | [array[j], array[j + 1]] = [array[j + 1], array[j]]; 10 | swapped = true; 11 | } 12 | } 13 | if (!swapped) break; 14 | } 15 | return array; 16 | } 17 | 18 | /** 19 | * Sorts an array using quick sort 20 | */ 21 | export function quickSort(array: number[]): number[] { 22 | array = array.slice(); 23 | partition(array, 0, array.length); 24 | return array; 25 | } 26 | 27 | function partition(array: number[], start: number, before: number): void { 28 | const length = before - start; 29 | 30 | if (length <= 1) return; 31 | const pivotIndex = start + Math.floor(Math.random() * length); 32 | [array[start], array[pivotIndex]] = [array[pivotIndex], array[start]]; 33 | const pivot = array[start]; 34 | let pivotRank = start; 35 | for (let index = start + 1; index < before; index++) { 36 | if (array[index] < pivot) { 37 | pivotRank++; 38 | [array[index], array[pivotRank]] = [array[pivotRank], array[index]]; 39 | } 40 | } 41 | if (pivotRank !== start) { 42 | [array[pivotRank], array[start]] = [array[start], array[pivotRank]]; 43 | } 44 | partition(array, start, pivotRank); 45 | partition(array, pivotRank + 1, before); 46 | } 47 | 48 | /** 49 | * Sorts an array using insertion sort 50 | */ 51 | export function insertionSort(array: number[]): number[] { 52 | array = array.slice(); 53 | for (let i = 1; i < array.length; i++) { 54 | const current = array[i]; 55 | let j = i - 1; 56 | while (j >= 0 && array[j] > current) { 57 | array[j + 1] = array[j]; 58 | j--; 59 | } 60 | array[j + 1] = current; 61 | } 62 | return array; 63 | } 64 | 65 | /** 66 | * Sorts an array using merge sort 67 | */ 68 | export function mergeSort(array: number[]): number[] { 69 | if (array.length <= 1) { 70 | return array; 71 | } 72 | const middle = Math.floor(array.length / 2); 73 | const left = array.slice(0, middle); 74 | const right = array.slice(middle); 75 | 76 | return merge(mergeSort(left), mergeSort(right)); 77 | } 78 | function merge(left: number[], right: number[]): number[] { 79 | const array: number[] = []; 80 | let lIndex = 0; 81 | let rIndex = 0; 82 | while (lIndex + rIndex < left.length + right.length) { 83 | const lItem = left[lIndex]; 84 | const rItem = right[rIndex]; 85 | if (lItem == null) { 86 | array.push(rItem); rIndex++; 87 | } 88 | else if (rItem == null) { 89 | array.push(lItem); lIndex++; 90 | } 91 | else if (lItem < rItem) { 92 | array.push(lItem); lIndex++; 93 | } 94 | else { 95 | array.push(rItem); rIndex++; 96 | } 97 | } 98 | return array; 99 | } 100 | 101 | /** 102 | * Searches for specific element in a given sorted array 103 | * @returns the index of the element (-1 if its not found) 104 | */ 105 | export function binarySearch(array: number[], element: number, start = 0, end = array.length - 1): number { 106 | if (end < start) return -1; 107 | const middle = Math.floor((start + end) / 2); 108 | return element === array[middle] 109 | ? middle 110 | : element < array[middle] 111 | ? binarySearch(array, element, start, middle - 1) 112 | : binarySearch(array, element, middle + 1, end); 113 | } 114 | 115 | /** 116 | * Returns the first repeated item from an array if any 117 | * @throws {Error} if there is no item repetition 118 | */ 119 | function repeatedItemLoops(array: T[]): T { 120 | for (let i = 0; i < array.length; i++) { 121 | for (let j = i + 1; j < array.length; j++) { 122 | if (array[i] === array[j]) return array[i]; 123 | } 124 | } 125 | throw new Error('No item repetition'); 126 | } -------------------------------------------------------------------------------- /src/sArray.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | export function bubbleSort(array: number[]): number[] { 4 | array = array.slice(); 5 | while (true) { 6 | let swapped = false; 7 | for (let j = 0; j < array.length - 1; j++) { 8 | if (array[j] > array[j + 1]) { 9 | [array[j], array[j + 1]] = [array[j + 1], array[j]]; 10 | swapped = true; 11 | } 12 | } 13 | if (!swapped) break; 14 | } 15 | return array; 16 | } 17 | 18 | /** 19 | * Sorts an array using quick sort 20 | */ 21 | export function quickSort(array: number[]): number[] { 22 | array = array.slice(); 23 | partition(array, 0, array.length); 24 | return array; 25 | } 26 | 27 | function partition(array: number[], start: number, before: number): void { 28 | const length = before - start; 29 | 30 | if (length <= 1) return; 31 | const pivotIndex = start + Math.floor(Math.random() * length); 32 | [array[start], array[pivotIndex]] = [array[pivotIndex], array[start]]; 33 | const pivot = array[start]; 34 | let pivotRank = start; 35 | for (let index = start + 1; index < before; index++) { 36 | if (array[index] < pivot) { 37 | pivotRank++; 38 | [array[index], array[pivotRank]] = [array[pivotRank], array[index]]; 39 | } 40 | } 41 | if (pivotRank !== start) { 42 | [array[pivotRank], array[start]] = [array[start], array[pivotRank]]; 43 | } 44 | partition(array, start, pivotRank); 45 | partition(array, pivotRank + 1, before); 46 | } 47 | 48 | /** 49 | * Sorts an array using insertion sort 50 | */ 51 | export function insertionSort(array: number[]): number[] { 52 | array = array.slice(); 53 | for (let i = 1; i < array.length; i++) { 54 | const current = array[i]; 55 | let j = i - 1; 56 | while (j >= 0 && array[j] > current) { 57 | array[j + 1] = array[j]; 58 | j--; 59 | } 60 | array[j + 1] = current; 61 | } 62 | return array; 63 | } 64 | 65 | /** 66 | * Sorts an array using merge sort 67 | */ 68 | export function mergeSort(array: number[]): number[] { 69 | if (array.length <= 1) { 70 | return array; 71 | } 72 | const middle = Math.floor(array.length / 2); 73 | const left = array.slice(0, middle); 74 | const right = array.slice(middle); 75 | 76 | return merge(mergeSort(left), mergeSort(right)); 77 | } 78 | function merge(left: number[], right: number[]): number[] { 79 | const array: number[] = []; 80 | let lIndex = 0; 81 | let rIndex = 0; 82 | while (lIndex + rIndex < left.length + right.length) { 83 | const lItem = left[lIndex]; 84 | const rItem = right[rIndex]; 85 | if (lItem == null) { 86 | array.push(rItem); rIndex++; 87 | } 88 | else if (rItem == null) { 89 | array.push(lItem); lIndex++; 90 | } 91 | else if (lItem < rItem) { 92 | array.push(lItem); lIndex++; 93 | } 94 | else { 95 | array.push(rItem); rIndex++; 96 | } 97 | } 98 | return array; 99 | } 100 | 101 | /** 102 | * Searches for specific element in a given sorted array 103 | * @returns the index of the element (-1 if its not found) 104 | */ 105 | export function binarySearch(array: number[], element: number, start = 0, end = array.length - 1): number { 106 | if (end < start) return -1; 107 | const middle = Math.floor((start + end) / 2); 108 | return element === array[middle] 109 | ? middle 110 | : element < array[middle] 111 | ? binarySearch(array, element, start, middle - 1) 112 | : binarySearch(array, element, middle + 1, end); 113 | } 114 | 115 | /** 116 | * Returns the first repeated item from an array if any 117 | * @throws {Error} if there is no item repetition 118 | */ 119 | function repeatedItemLoops(array: T[]): T { 120 | for (let i = 0; i < array.length; i++) { 121 | for (let j = i + 1; j < array.length; j++) { 122 | if (array[i] === array[j]) return array[i]; 123 | } 124 | } 125 | throw new Error('No item repetition'); 126 | } -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | exports.__esModule = true; 3 | function bubbleSort(array) { 4 | array = array.slice(); 5 | while (true) { 6 | var swapped = false; 7 | for (var j = 0; j < array.length - 1; j++) { 8 | if (array[j] > array[j + 1]) { 9 | _a = [array[j + 1], array[j]], array[j] = _a[0], array[j + 1] = _a[1]; 10 | swapped = true; 11 | } 12 | } 13 | if (!swapped) 14 | break; 15 | } 16 | return array; 17 | var _a; 18 | } 19 | exports.bubbleSort = bubbleSort; 20 | /** 21 | * Sorts an array using quick sort 22 | */ 23 | function quickSort(array) { 24 | array = array.slice(); 25 | partition(array, 0, array.length); 26 | return array; 27 | } 28 | exports.quickSort = quickSort; 29 | function partition(array, start, before) { 30 | var length = before - start; 31 | if (length <= 1) 32 | return; 33 | var pivotIndex = start + Math.floor(Math.random() * length); 34 | _a = [array[pivotIndex], array[start]], array[start] = _a[0], array[pivotIndex] = _a[1]; 35 | var pivot = array[start]; 36 | var pivotRank = start; 37 | for (var index = start + 1; index < before; index++) { 38 | if (array[index] < pivot) { 39 | pivotRank++; 40 | _b = [array[pivotRank], array[index]], array[index] = _b[0], array[pivotRank] = _b[1]; 41 | } 42 | } 43 | if (pivotRank !== start) { 44 | _c = [array[start], array[pivotRank]], array[pivotRank] = _c[0], array[start] = _c[1]; 45 | } 46 | partition(array, start, pivotRank); 47 | partition(array, pivotRank + 1, before); 48 | var _a, _b, _c; 49 | } 50 | /** 51 | * Sorts an array using insertion sort 52 | */ 53 | function insertionSort(array) { 54 | array = array.slice(); 55 | for (var i = 1; i < array.length; i++) { 56 | var current = array[i]; 57 | var j = i - 1; 58 | while (j >= 0 && array[j] > current) { 59 | array[j + 1] = array[j]; 60 | j--; 61 | } 62 | array[j + 1] = current; 63 | } 64 | return array; 65 | } 66 | exports.insertionSort = insertionSort; 67 | /** 68 | * Sorts an array using merge sort 69 | */ 70 | function mergeSort(array) { 71 | if (array.length <= 1) { 72 | return array; 73 | } 74 | var middle = Math.floor(array.length / 2); 75 | var left = array.slice(0, middle); 76 | var right = array.slice(middle); 77 | return merge(mergeSort(left), mergeSort(right)); 78 | } 79 | exports.mergeSort = mergeSort; 80 | function merge(left, right) { 81 | var array = []; 82 | var lIndex = 0; 83 | var rIndex = 0; 84 | while (lIndex + rIndex < left.length + right.length) { 85 | var lItem = left[lIndex]; 86 | var rItem = right[rIndex]; 87 | if (lItem == null) { 88 | array.push(rItem); 89 | rIndex++; 90 | } 91 | else if (rItem == null) { 92 | array.push(lItem); 93 | lIndex++; 94 | } 95 | else if (lItem < rItem) { 96 | array.push(lItem); 97 | lIndex++; 98 | } 99 | else { 100 | array.push(rItem); 101 | rIndex++; 102 | } 103 | } 104 | return array; 105 | } 106 | /** 107 | * Searches for specific element in a given sorted array 108 | * @returns the index of the element (-1 if its not found) 109 | */ 110 | function binarySearch(array, element, start, end) { 111 | if (start === void 0) { start = 0; } 112 | if (end === void 0) { end = array.length - 1; } 113 | if (end < start) 114 | return -1; 115 | var middle = Math.floor((start + end) / 2); 116 | return element === array[middle] 117 | ? middle 118 | : element < array[middle] 119 | ? binarySearch(array, element, start, middle - 1) 120 | : binarySearch(array, element, middle + 1, end); 121 | } 122 | exports.binarySearch = binarySearch; 123 | /** 124 | * Returns the first repeated item from an array if any 125 | * @throws {Error} if there is no item repetition 126 | */ 127 | function repeatedItemLoops(array) { 128 | for (var i = 0; i < array.length; i++) { 129 | for (var j = i + 1; j < array.length; j++) { 130 | if (array[i] === array[j]) 131 | return array[i]; 132 | } 133 | } 134 | throw new Error('No item repetition'); 135 | } 136 | -------------------------------------------------------------------------------- /lib/sArray.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | exports.__esModule = true; 3 | function bubbleSort(array) { 4 | array = array.slice(); 5 | while (true) { 6 | var swapped = false; 7 | for (var j = 0; j < array.length - 1; j++) { 8 | if (array[j] > array[j + 1]) { 9 | _a = [array[j + 1], array[j]], array[j] = _a[0], array[j + 1] = _a[1]; 10 | swapped = true; 11 | } 12 | } 13 | if (!swapped) 14 | break; 15 | } 16 | return array; 17 | var _a; 18 | } 19 | exports.bubbleSort = bubbleSort; 20 | /** 21 | * Sorts an array using quick sort 22 | */ 23 | function quickSort(array) { 24 | array = array.slice(); 25 | partition(array, 0, array.length); 26 | return array; 27 | } 28 | exports.quickSort = quickSort; 29 | function partition(array, start, before) { 30 | var length = before - start; 31 | if (length <= 1) 32 | return; 33 | var pivotIndex = start + Math.floor(Math.random() * length); 34 | _a = [array[pivotIndex], array[start]], array[start] = _a[0], array[pivotIndex] = _a[1]; 35 | var pivot = array[start]; 36 | var pivotRank = start; 37 | for (var index = start + 1; index < before; index++) { 38 | if (array[index] < pivot) { 39 | pivotRank++; 40 | _b = [array[pivotRank], array[index]], array[index] = _b[0], array[pivotRank] = _b[1]; 41 | } 42 | } 43 | if (pivotRank !== start) { 44 | _c = [array[start], array[pivotRank]], array[pivotRank] = _c[0], array[start] = _c[1]; 45 | } 46 | partition(array, start, pivotRank); 47 | partition(array, pivotRank + 1, before); 48 | var _a, _b, _c; 49 | } 50 | /** 51 | * Sorts an array using insertion sort 52 | */ 53 | function insertionSort(array) { 54 | array = array.slice(); 55 | for (var i = 1; i < array.length; i++) { 56 | var current = array[i]; 57 | var j = i - 1; 58 | while (j >= 0 && array[j] > current) { 59 | array[j + 1] = array[j]; 60 | j--; 61 | } 62 | array[j + 1] = current; 63 | } 64 | return array; 65 | } 66 | exports.insertionSort = insertionSort; 67 | /** 68 | * Sorts an array using merge sort 69 | */ 70 | function mergeSort(array) { 71 | if (array.length <= 1) { 72 | return array; 73 | } 74 | var middle = Math.floor(array.length / 2); 75 | var left = array.slice(0, middle); 76 | var right = array.slice(middle); 77 | return merge(mergeSort(left), mergeSort(right)); 78 | } 79 | exports.mergeSort = mergeSort; 80 | function merge(left, right) { 81 | var array = []; 82 | var lIndex = 0; 83 | var rIndex = 0; 84 | while (lIndex + rIndex < left.length + right.length) { 85 | var lItem = left[lIndex]; 86 | var rItem = right[rIndex]; 87 | if (lItem == null) { 88 | array.push(rItem); 89 | rIndex++; 90 | } 91 | else if (rItem == null) { 92 | array.push(lItem); 93 | lIndex++; 94 | } 95 | else if (lItem < rItem) { 96 | array.push(lItem); 97 | lIndex++; 98 | } 99 | else { 100 | array.push(rItem); 101 | rIndex++; 102 | } 103 | } 104 | return array; 105 | } 106 | /** 107 | * Searches for specific element in a given sorted array 108 | * @returns the index of the element (-1 if its not found) 109 | */ 110 | function binarySearch(array, element, start, end) { 111 | if (start === void 0) { start = 0; } 112 | if (end === void 0) { end = array.length - 1; } 113 | if (end < start) 114 | return -1; 115 | var middle = Math.floor((start + end) / 2); 116 | return element === array[middle] 117 | ? middle 118 | : element < array[middle] 119 | ? binarySearch(array, element, start, middle - 1) 120 | : binarySearch(array, element, middle + 1, end); 121 | } 122 | exports.binarySearch = binarySearch; 123 | /** 124 | * Returns the first repeated item from an array if any 125 | * @throws {Error} if there is no item repetition 126 | */ 127 | function repeatedItemLoops(array) { 128 | for (var i = 0; i < array.length; i++) { 129 | for (var j = i + 1; j < array.length; j++) { 130 | if (array[i] === array[j]) 131 | return array[i]; 132 | } 133 | } 134 | throw new Error('No item repetition'); 135 | } 136 | -------------------------------------------------------------------------------- /src/protos/Arrays.ts: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Check if all the variables in the array are truthy 4 | * @returns {boolean} 5 | */ 6 | Array.prototype.isAllTrue = (): boolean => { 7 | return this.reduce((pv, cv) => { return (typeof cv === 'boolean') ? (!pv) ? pv : cv : false }, true); 8 | }; 9 | 10 | /** 11 | * Sort with correct ordering 12 | * @prevents 13 | * [3, 22, 1] ===> [1, 22, 3] 14 | * 15 | * @param {(a: any, b: any) => number} cb 16 | * @returns {Array} 17 | */ 18 | Array.prototype.sort = (cb: (a: T, b: T) => number): Array => { 19 | return (typeof cb === 'function') ? this.sort(cb) : this.sort((a, b) => a - b); 20 | }; 21 | 22 | /** 23 | * Sort array by key 24 | * 25 | * @param {string} key 26 | * @returns {any} 27 | */ 28 | Array.prototype.sortBy = (key: string) => { 29 | return this.sort((a, b) => a[key] - b[key]); 30 | }; 31 | 32 | /** 33 | * Bubble sort 34 | */ 35 | Array.prototype.bubbleSort = (): number[] => { 36 | let array = this.slice(); 37 | while (true) { 38 | let swapped = false; 39 | for (let j = 0; j < array.length - 1; j++) { 40 | if (array[j] > array[j + 1]) { 41 | [array[j], array[j + 1]] = [array[j + 1], array[j]]; 42 | swapped = true; 43 | } 44 | } 45 | if (!swapped) break; 46 | } 47 | return array; 48 | }; 49 | 50 | 51 | /** 52 | * Sorts an array using quick sort 53 | */ 54 | Array.prototype.quickSort = (): number[] => { 55 | let array = this.slice(); 56 | ArrayHelpers.partition(array, 0, array.length); 57 | return array; 58 | }; 59 | 60 | /** 61 | * Insert sort for arrays 62 | */ 63 | Array.prototype.insertionSort = (): number[] => { 64 | let array = this.slice(); 65 | for (let i = 1; i < array.length; i++) { 66 | const current = array[i]; 67 | let j = i - 1; 68 | while (j >= 0 && array[j] > current) { 69 | array[j + 1] = array[j]; 70 | j--; 71 | } 72 | array[j + 1] = current; 73 | } 74 | return array; 75 | }; 76 | 77 | 78 | /** 79 | * Sorts an array using merge sort 80 | */ 81 | Array.prototype.mergeSort = (): number[] => { 82 | if (this.length <= 1) { 83 | return this; 84 | } 85 | const middle = Math.floor(this.length / 2); 86 | const left = this.slice(0, middle); 87 | const right = this.slice(middle); 88 | 89 | return ArrayHelpers.merge(left.mergeSort(), right.mergeSort()); 90 | }; 91 | 92 | /** 93 | * Searches for specific element in a given sorted array 94 | * @returns the index of the element (-1 if its not found) 95 | */ 96 | Array.prototype.binarySearch = (element: number, start = 0, end = this.length - 1): number => { 97 | if (end < start) return -1; 98 | const middle = Math.floor((start + end) / 2); 99 | return element === this[middle] 100 | ? middle 101 | : element < this[middle] 102 | ? this.binarySearch(element, start, middle - 1) 103 | : this.binarySearch(element, middle + 1, end); 104 | }; 105 | 106 | /** 107 | * Returns the first repeated item from an array if any 108 | * @throws {Error} if there is no item repetition 109 | */ 110 | Array.prototype.firstRepeatedItem = (): T => { 111 | const set = []; 112 | for (const item of this) { 113 | if (set[item]) return item; 114 | else set.push(item); 115 | } 116 | throw new Error('No item repetition'); 117 | }; 118 | 119 | module ArrayHelpers { 120 | /** 121 | * Partition for quick sort 122 | */ 123 | export function partition(array: number[], start: number, before: number): void { 124 | const length = before - start; 125 | 126 | if (length <= 1) return; 127 | 128 | const pivotIndex = start + Math.floor(Math.random() * length); 129 | [array[start], array[pivotIndex]] = [array[pivotIndex], array[start]]; 130 | 131 | const pivot = array[start]; 132 | let pivotRank = start; 133 | 134 | for (let index = start + 1; index < before; index++) { 135 | if (array[index] < pivot) { 136 | pivotRank++; 137 | [array[index], array[pivotRank]] = [array[pivotRank], array[index]]; 138 | } 139 | } 140 | if (pivotRank !== start) { 141 | [array[pivotRank], array[start]] = [array[start], array[pivotRank]]; 142 | } 143 | 144 | ArrayHelpers.partition(array, start, pivotRank); 145 | ArrayHelpers.partition(array, pivotRank + 1, before); 146 | } 147 | 148 | /** Merge (conquer) step of mergeSort */ 149 | export function merge(left: number[], right: number[]): number[] { 150 | const array: number[] = []; 151 | let lIndex = 0; 152 | let rIndex = 0; 153 | while (lIndex + rIndex < left.length + right.length) { 154 | const lItem = left[lIndex]; 155 | const rItem = right[rIndex]; 156 | if (lItem == null) { 157 | array.push(rItem); rIndex++; 158 | } 159 | else if (rItem == null) { 160 | array.push(lItem); lIndex++; 161 | } 162 | else if (lItem < rItem) { 163 | array.push(lItem); lIndex++; 164 | } 165 | else { 166 | array.push(rItem); rIndex++; 167 | } 168 | } 169 | return array; 170 | } 171 | } -------------------------------------------------------------------------------- /lib/protos/Arrays.js: -------------------------------------------------------------------------------- 1 | var _this = this; 2 | /** 3 | * Check if all the variables in the array are truthy 4 | * @returns {boolean} 5 | */ 6 | Array.prototype.isAllTrue = function () { 7 | return _this.reduce(function (pv, cv) { return (typeof cv === 'boolean') ? (!pv) ? pv : cv : false; }, true); 8 | }; 9 | /** 10 | * Sort with correct ordering 11 | * @prevents 12 | * [3, 22, 1] ===> [1, 22, 3] 13 | * 14 | * @param {(a: any, b: any) => number} cb 15 | * @returns {Array} 16 | */ 17 | Array.prototype.sort = function (cb) { 18 | return (typeof cb === 'function') ? _this.sort(cb) : _this.sort(function (a, b) { return a - b; }); 19 | }; 20 | /** 21 | * Sort array by key 22 | * 23 | * @param {string} key 24 | * @returns {any} 25 | */ 26 | Array.prototype.sortBy = function (key) { 27 | return _this.sort(function (a, b) { return a[key] - b[key]; }); 28 | }; 29 | /** 30 | * Bubble sort 31 | */ 32 | Array.prototype.bubbleSort = function () { 33 | var array = _this.slice(); 34 | while (true) { 35 | var swapped = false; 36 | for (var j = 0; j < array.length - 1; j++) { 37 | if (array[j] > array[j + 1]) { 38 | _a = [array[j + 1], array[j]], array[j] = _a[0], array[j + 1] = _a[1]; 39 | swapped = true; 40 | } 41 | } 42 | if (!swapped) 43 | break; 44 | } 45 | return array; 46 | var _a; 47 | }; 48 | /** 49 | * Sorts an array using quick sort 50 | */ 51 | Array.prototype.quickSort = function () { 52 | var array = _this.slice(); 53 | ArrayHelpers.partition(array, 0, array.length); 54 | return array; 55 | }; 56 | /** 57 | * Insert sort for arrays 58 | */ 59 | Array.prototype.insertionSort = function () { 60 | var array = _this.slice(); 61 | for (var i = 1; i < array.length; i++) { 62 | var current = array[i]; 63 | var j = i - 1; 64 | while (j >= 0 && array[j] > current) { 65 | array[j + 1] = array[j]; 66 | j--; 67 | } 68 | array[j + 1] = current; 69 | } 70 | return array; 71 | }; 72 | /** 73 | * Sorts an array using merge sort 74 | */ 75 | Array.prototype.mergeSort = function () { 76 | if (_this.length <= 1) { 77 | return _this; 78 | } 79 | var middle = Math.floor(_this.length / 2); 80 | var left = _this.slice(0, middle); 81 | var right = _this.slice(middle); 82 | return ArrayHelpers.merge(left.mergeSort(), right.mergeSort()); 83 | }; 84 | /** 85 | * Searches for specific element in a given sorted array 86 | * @returns the index of the element (-1 if its not found) 87 | */ 88 | Array.prototype.binarySearch = function (element, start, end) { 89 | if (start === void 0) { start = 0; } 90 | if (end === void 0) { end = _this.length - 1; } 91 | if (end < start) 92 | return -1; 93 | var middle = Math.floor((start + end) / 2); 94 | return element === _this[middle] 95 | ? middle 96 | : element < _this[middle] 97 | ? _this.binarySearch(element, start, middle - 1) 98 | : _this.binarySearch(element, middle + 1, end); 99 | }; 100 | /** 101 | * Returns the first repeated item from an array if any 102 | * @throws {Error} if there is no item repetition 103 | */ 104 | Array.prototype.firstRepeatedItem = function () { 105 | var set = []; 106 | for (var _i = 0, _a = _this; _i < _a.length; _i++) { 107 | var item = _a[_i]; 108 | if (set[item]) 109 | return item; 110 | else 111 | set.push(item); 112 | } 113 | throw new Error('No item repetition'); 114 | }; 115 | var ArrayHelpers; 116 | (function (ArrayHelpers) { 117 | /** 118 | * Partition for quick sort 119 | */ 120 | function partition(array, start, before) { 121 | var length = before - start; 122 | if (length <= 1) 123 | return; 124 | var pivotIndex = start + Math.floor(Math.random() * length); 125 | _a = [array[pivotIndex], array[start]], array[start] = _a[0], array[pivotIndex] = _a[1]; 126 | var pivot = array[start]; 127 | var pivotRank = start; 128 | for (var index = start + 1; index < before; index++) { 129 | if (array[index] < pivot) { 130 | pivotRank++; 131 | _b = [array[pivotRank], array[index]], array[index] = _b[0], array[pivotRank] = _b[1]; 132 | } 133 | } 134 | if (pivotRank !== start) { 135 | _c = [array[start], array[pivotRank]], array[pivotRank] = _c[0], array[start] = _c[1]; 136 | } 137 | ArrayHelpers.partition(array, start, pivotRank); 138 | ArrayHelpers.partition(array, pivotRank + 1, before); 139 | var _a, _b, _c; 140 | } 141 | ArrayHelpers.partition = partition; 142 | /** Merge (conquer) step of mergeSort */ 143 | function merge(left, right) { 144 | var array = []; 145 | var lIndex = 0; 146 | var rIndex = 0; 147 | while (lIndex + rIndex < left.length + right.length) { 148 | var lItem = left[lIndex]; 149 | var rItem = right[rIndex]; 150 | if (lItem == null) { 151 | array.push(rItem); 152 | rIndex++; 153 | } 154 | else if (rItem == null) { 155 | array.push(lItem); 156 | lIndex++; 157 | } 158 | else if (lItem < rItem) { 159 | array.push(lItem); 160 | lIndex++; 161 | } 162 | else { 163 | array.push(rItem); 164 | rIndex++; 165 | } 166 | } 167 | return array; 168 | } 169 | ArrayHelpers.merge = merge; 170 | })(ArrayHelpers || (ArrayHelpers = {})); 171 | --------------------------------------------------------------------------------