UNPKG

@tzm96dev/algo-toolkit

Version:

Algorithms Kit: A TypeScript-first library of classic and modern algorithms. Includes sorting, searching, and string-matching utilities for arrays, numbers, and objects. Lightweight, fast, and production-ready.

397 lines (377 loc) 12.8 kB
// src/utils/comparator.ts function getValue(item, key) { if (!key) return item; if (typeof key === "function") return key(item); return item[key]; } function defaultPrimitiveComparator(a, b) { if (typeof a === "number" && typeof b === "number") return a - b; if (typeof a === "string" && typeof b === "string") return a.localeCompare(b); return String(a).localeCompare(String(b)); } function buildComparator(opts) { var _a; const order = (_a = opts == null ? void 0 : opts.order) != null ? _a : "asc"; return (a, b) => { const va = getValue(a, opts == null ? void 0 : opts.key); const vb = getValue(b, opts == null ? void 0 : opts.key); const r = defaultPrimitiveComparator(va, vb); return order === "asc" ? r : -r; }; } // src/sorting/bubbleSort.ts function bubbleSort(arr, opts) { const comparator = buildComparator(opts); const a = [...arr]; for (let i = 0; i < a.length - 1; i++) { let swapped = false; for (let j = 0; j < a.length - i - 1; j++) { if (comparator(a[j], a[j + 1]) > 0) { [a[j], a[j + 1]] = [a[j + 1], a[j]]; swapped = true; } } if (!swapped) break; } return a; } // src/sorting/insertionSort.ts function insertionSort(arr, opts) { const comparator = buildComparator(opts); const a = [...arr]; for (let i = 1; i < a.length; i++) { const key = a[i]; let j = i - 1; while (j >= 0 && comparator(a[j], key) > 0) { a[j + 1] = a[j]; j--; } a[j + 1] = key; } return a; } // src/sorting/selectionSort.ts function selectionSort(arr, opts) { const comparator = buildComparator(opts); const a = [...arr]; for (let i = 0; i < a.length - 1; i++) { let minIdx = i; for (let j = i + 1; j < a.length; j++) { if (comparator(a[j], a[minIdx]) < 0) minIdx = j; } if (minIdx !== i) [a[i], a[minIdx]] = [a[minIdx], a[i]]; } return a; } // src/sorting/mergeSort.ts function merge(left, right, cmp) { const result = []; let i = 0, j = 0; while (i < left.length && j < right.length) { if (cmp(left[i], right[j]) <= 0) result.push(left[i++]); else result.push(right[j++]); } return result.concat(left.slice(i)).concat(right.slice(j)); } function mergeSort(arr, opts) { if (arr.length <= 1) return arr; const cmp = buildComparator(opts); const mid = Math.floor(arr.length / 2); const left = mergeSort(arr.slice(0, mid), opts); const right = mergeSort(arr.slice(mid), opts); return merge(left, right, cmp); } // src/sorting/quickSort.ts function quickSort(arr, opts) { if (arr.length <= 1) return arr; const cmp = buildComparator(opts); const pivot = arr[arr.length - 1]; const left = []; const right = []; for (let i = 0; i < arr.length - 1; i++) { if (cmp(arr[i], pivot) <= 0) left.push(arr[i]); else right.push(arr[i]); } return [...quickSort(left, opts), pivot, ...quickSort(right, opts)]; } // src/sorting/heapSort.ts function heapify(a, n, i, cmp) { let largest = i; const l = 2 * i + 1, r = 2 * i + 2; if (l < n && cmp(a[l], a[largest]) > 0) largest = l; if (r < n && cmp(a[r], a[largest]) > 0) largest = r; if (largest !== i) { [a[i], a[largest]] = [a[largest], a[i]]; heapify(a, n, largest, cmp); } } function heapSort(arr, opts) { const a = [...arr]; const cmp = buildComparator(opts); const n = a.length; for (let i = Math.floor(n / 2) - 1; i >= 0; i--) heapify(a, n, i, cmp); for (let i = n - 1; i > 0; i--) { [a[0], a[i]] = [a[i], a[0]]; heapify(a, i, 0, cmp); } if ((opts == null ? void 0 : opts.order) === "desc") return a.reverse(); return a; } // src/sorting/countingSort.ts function countingSort(arr, opts) { var _a, _b; if (arr.length === 0) return []; const min = (_a = opts == null ? void 0 : opts.min) != null ? _a : Math.min(...arr); const max = (_b = opts == null ? void 0 : opts.max) != null ? _b : Math.max(...arr); const range = max - min + 1; const count = new Array(range).fill(0); const output = new Array(arr.length); for (const num of arr) count[num - min]++; for (let i = 1; i < count.length; i++) count[i] += count[i - 1]; for (let i = arr.length - 1; i >= 0; i--) { const num = arr[i]; const idx = num - min; output[count[idx] - 1] = num; count[idx]--; } return output; } // src/sorting/radixSort.ts function radixSortNonNegative(arr) { if (arr.length === 0) return []; let max = Math.max(...arr); let exp = 1; let output = [...arr]; while (Math.floor(max / exp) > 0) { const count = new Array(10).fill(0); const out = new Array(output.length).fill(0); for (const num of output) count[Math.floor(num / exp) % 10]++; for (let i = 1; i < 10; i++) count[i] += count[i - 1]; for (let i = output.length - 1; i >= 0; i--) { const num = output[i]; const idx = Math.floor(num / exp) % 10; out[count[idx] - 1] = num; count[idx]--; } output = out; exp *= 10; } return output; } function radixSort(arr) { const negatives = arr.filter((n) => n < 0).map((n) => Math.abs(n)); const nonNegatives = arr.filter((n) => n >= 0); const sortedNeg = radixSortNonNegative(negatives).reverse().map((n) => -n); const sortedPos = radixSortNonNegative(nonNegatives); return [...sortedNeg, ...sortedPos]; } // src/sorting/bucketSort.ts function bucketSort(arr, opts) { var _a, _b, _c; const n = arr.length; if (n <= 1) return [...arr]; const min = (_a = opts == null ? void 0 : opts.min) != null ? _a : Math.min(...arr); const max = (_b = opts == null ? void 0 : opts.max) != null ? _b : Math.max(...arr); const bucketCount = Math.max(1, (_c = opts == null ? void 0 : opts.bucketCount) != null ? _c : Math.ceil(Math.sqrt(n))); const buckets = Array.from({ length: bucketCount }, () => []); const range = max - min || 1; for (const num of arr) { const idx = Math.min(bucketCount - 1, Math.floor((num - min) / range * bucketCount)); buckets[idx].push(num); } for (const b of buckets) b.sort((a, b2) => a - b2); return [].concat(...buckets); } // src/searching/linearSearch.ts function linearSearch(arr, target, opts) { for (let i = 0; i < arr.length; i++) { const val = getValue(arr[i], opts == null ? void 0 : opts.key); if (val === target) return i; } return -1; } // src/searching/binarySearch.ts function binarySearch(arr, target, opts) { var _a; const order = (_a = opts == null ? void 0 : opts.order) != null ? _a : "asc"; let low = 0, high = arr.length - 1; while (low <= high) { const mid = Math.floor((low + high) / 2); const midVal = getValue(arr[mid], opts == null ? void 0 : opts.key); const cmp = defaultPrimitiveComparator(midVal, target); if (cmp === 0) return mid; if (order === "asc") { if (cmp < 0) low = mid + 1; else high = mid - 1; } else { if (cmp > 0) low = mid + 1; else high = mid - 1; } } return -1; } // src/searching/jumpSearch.ts function jumpSearch(arr, target, opts) { var _a; const n = arr.length; if (n === 0) return -1; const order = (_a = opts == null ? void 0 : opts.order) != null ? _a : "asc"; const step = Math.max(1, Math.floor(Math.sqrt(n))); let prev = 0; let current = step; const cmpDir = (a, b) => order === "asc" ? defaultPrimitiveComparator(a, b) : defaultPrimitiveComparator(b, a); while (prev < n && cmpDir(getValue(arr[Math.min(current, n) - 1], opts == null ? void 0 : opts.key), target) < 0) { prev = current; current += step; if (prev >= n) return -1; } while (prev < Math.min(current, n)) { if (defaultPrimitiveComparator(getValue(arr[prev], opts == null ? void 0 : opts.key), target) === 0) return prev; prev++; } return -1; } // src/searching/interpolationSearch.ts function interpolationSearch(arr, target) { let low = 0, high = arr.length - 1; while (low <= high && target >= arr[low] && target <= arr[high]) { if (low === high) return arr[low] === target ? low : -1; const pos = low + Math.floor((target - arr[low]) * (high - low) / (arr[high] - arr[low])); if (arr[pos] === target) return pos; if (arr[pos] < target) low = pos + 1; else high = pos - 1; } return -1; } // src/searching/exponentialSearch.ts function exponentialSearch(arr, target, opts) { var _a; const n = arr.length; if (n === 0) return -1; const order = (_a = opts == null ? void 0 : opts.order) != null ? _a : "asc"; const cmpDir = (a, b) => order === "asc" ? defaultPrimitiveComparator(a, b) : defaultPrimitiveComparator(b, a); if (defaultPrimitiveComparator(getValue(arr[0], opts == null ? void 0 : opts.key), target) === 0) return 0; let i = 1; while (i < n && cmpDir(getValue(arr[i], opts == null ? void 0 : opts.key), target) <= 0) i *= 2; let low = Math.floor(i / 2), high = Math.min(i, n - 1); while (low <= high) { const mid = Math.floor((low + high) / 2); const midVal = getValue(arr[mid], opts == null ? void 0 : opts.key); const cmp = defaultPrimitiveComparator(midVal, target); if (cmp === 0) return mid; if (order === "asc") { if (cmp < 0) low = mid + 1; else high = mid - 1; } else { if (cmp > 0) low = mid + 1; else high = mid - 1; } } return -1; } // src/searching/ternarySearch.ts function ternarySearch(arr, target, opts) { var _a; let l = 0, r = arr.length - 1; const order = (_a = opts == null ? void 0 : opts.order) != null ? _a : "asc"; const cmpDir = (a, b) => order === "asc" ? defaultPrimitiveComparator(a, b) : defaultPrimitiveComparator(b, a); while (r >= l) { const mid1 = l + Math.floor((r - l) / 3); const mid2 = r - Math.floor((r - l) / 3); const v1 = getValue(arr[mid1], opts == null ? void 0 : opts.key); const v2 = getValue(arr[mid2], opts == null ? void 0 : opts.key); if (defaultPrimitiveComparator(v1, target) === 0) return mid1; if (defaultPrimitiveComparator(v2, target) === 0) return mid2; if (cmpDir(target, v1) < 0) r = mid1 - 1; else if (cmpDir(target, v2) > 0) l = mid2 + 1; else { l = mid1 + 1; r = mid2 - 1; } } return -1; } // src/searching/fibonacciSearch.ts function fibonacciSearch(arr, target) { const n = arr.length; let fibMMm2 = 0, fibMMm1 = 1, fibM = fibMMm2 + fibMMm1; while (fibM < n) { fibMMm2 = fibMMm1; fibMMm1 = fibM; fibM = fibMMm2 + fibMMm1; } let offset = -1; while (fibM > 1) { const i = Math.min(offset + fibMMm2, n - 1); if (arr[i] < target) { fibM = fibMMm1; fibMMm1 = fibMMm2; fibMMm2 = fibM - fibMMm1; offset = i; } else if (arr[i] > target) { fibM = fibMMm2; fibMMm1 = fibMMm1 - fibMMm2; fibMMm2 = fibM - fibMMm1; } else return i; } if (fibMMm1 && arr[offset + 1] === target) return offset + 1; return -1; } // src/searching/hashSearch.ts function hashSearch(arr, target, opts) { const map = /* @__PURE__ */ new Map(); for (let i = 0; i < arr.length; i++) { const v = getValue(arr[i], opts == null ? void 0 : opts.key); if (!map.has(v)) map.set(v, i); } return map.has(target) ? map.get(target) : -1; } // src/searching/kmpSearch.ts function kmpSearch(text, pattern) { if (pattern.length === 0) return 0; const lps = new Array(pattern.length).fill(0); let len = 0; for (let i2 = 1; i2 < pattern.length; ) { if (pattern[i2] === pattern[len]) lps[i2++] = ++len; else if (len) len = lps[len - 1]; else lps[i2++] = 0; } let i = 0, j = 0; while (i < text.length) { if (text[i] === pattern[j]) { i++; j++; if (j === pattern.length) return i - j; } else if (j) j = lps[j - 1]; else i++; } return -1; } // src/searching/rabinKarpSearch.ts function rabinKarpSearch(text, pattern, prime = 101) { const m = pattern.length, n = text.length; if (m === 0) return 0; if (m > n) return -1; const d = 256; let p = 0, t = 0, h = 1; for (let i = 0; i < m - 1; i++) h = h * d % prime; for (let i = 0; i < m; i++) { p = (d * p + pattern.charCodeAt(i)) % prime; t = (d * t + text.charCodeAt(i)) % prime; } for (let i = 0; i <= n - m; i++) { if (p === t) { let j = 0; while (j < m && text[i + j] === pattern[j]) j++; if (j === m) return i; } if (i < n - m) { t = (d * (t - text.charCodeAt(i) * h) + text.charCodeAt(i + m)) % prime; if (t < 0) t += prime; } } return -1; } export { binarySearch, bubbleSort, bucketSort, buildComparator, countingSort, defaultPrimitiveComparator, exponentialSearch, fibonacciSearch, getValue, hashSearch, heapSort, insertionSort, interpolationSearch, jumpSearch, kmpSearch, linearSearch, mergeSort, quickSort, rabinKarpSearch, radixSort, selectionSort, ternarySearch }; //# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map