@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.
420 lines (399 loc) • 13.3 kB
JavaScript
'use strict';
// 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;
}
exports.binarySearch = binarySearch;
exports.bubbleSort = bubbleSort;
exports.bucketSort = bucketSort;
exports.buildComparator = buildComparator;
exports.countingSort = countingSort;
exports.defaultPrimitiveComparator = defaultPrimitiveComparator;
exports.exponentialSearch = exponentialSearch;
exports.fibonacciSearch = fibonacciSearch;
exports.getValue = getValue;
exports.hashSearch = hashSearch;
exports.heapSort = heapSort;
exports.insertionSort = insertionSort;
exports.interpolationSearch = interpolationSearch;
exports.jumpSearch = jumpSearch;
exports.kmpSearch = kmpSearch;
exports.linearSearch = linearSearch;
exports.mergeSort = mergeSort;
exports.quickSort = quickSort;
exports.rabinKarpSearch = rabinKarpSearch;
exports.radixSort = radixSort;
exports.selectionSort = selectionSort;
exports.ternarySearch = ternarySearch;
//# sourceMappingURL=index.cjs.map
//# sourceMappingURL=index.cjs.map