diff --git a/.gitignore b/.gitignore index 26c3533..60cfa81 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ node_modules -.npmrc \ No newline at end of file +.npmrc + +dist +node_modules \ No newline at end of file diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..84a86bb --- /dev/null +++ b/.npmignore @@ -0,0 +1,2 @@ +scripts +src \ No newline at end of file diff --git a/README.md b/README.md index 94c2980..ce44b00 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,25 @@ Install quick-median with npm: npm install quick-median ``` +### CommonJS +```javascript +const { findMedian } = require('quick-median'); + +const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; +const median = findMedian(arr); +console.log(median); // 5.5 +``` + +### ES Module (TypeScript Supported) +```javascript +import findMedian from 'quick-median'; + +const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; +const median = findMedian(arr); +console.log(median); // 5.5 + +``` + ## Why this project? Many existing median-finding packages on npm are not optimized for performance. This project implements the Floyd-Rivest algorithm, a highly efficient selection algorithm that outperforms traditional quickselect in practice. diff --git a/dist/cjs/index.d.ts b/dist/cjs/index.d.ts deleted file mode 100644 index e2d358e..0000000 --- a/dist/cjs/index.d.ts +++ /dev/null @@ -1 +0,0 @@ -export default function findMedian(arr: number[]): number; diff --git a/dist/cjs/index.js b/dist/cjs/index.js index 9bd307e..5cc6b67 100644 --- a/dist/cjs/index.js +++ b/dist/cjs/index.js @@ -1,5 +1,6 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); +exports.findMedian = findMedian; function SELECT(X, L, R, K) { while (R > L) { if (R - L > 600) { diff --git a/dist/esm/index.d.ts b/dist/esm/index.d.ts deleted file mode 100644 index e2d358e..0000000 --- a/dist/esm/index.d.ts +++ /dev/null @@ -1 +0,0 @@ -export default function findMedian(arr: number[]): number; diff --git a/dist/esm/index.js b/dist/esm/index.js deleted file mode 100644 index 7bed6e8..0000000 --- a/dist/esm/index.js +++ /dev/null @@ -1,56 +0,0 @@ -function SELECT(X, L, R, K) { - while (R > L) { - if (R - L > 600) { - const N = R - L + 1; - const I = K - L + 1; - const Z = Math.log(N); - const S = 0.5 * Math.exp((2 * Z) / 3); - const SD = 0.5 * Math.sqrt((Z * S * (N - S)) / N) * Math.sign(I - N / 2); - const LL = Math.max(L, Math.floor(K - (I * S) / N + SD)); - const RR = Math.min(R, Math.floor(K + ((N - I) * S) / N + SD)); - SELECT(X, LL, RR, K); - } - const T = X[K]; - let I = L; - let J = R; - swap(X, L, K); - if (X[R] > T) - swap(X, R, L); - while (I < J) { - swap(X, I, J); - I++; - J--; - while (X[I] < T) - I++; - while (X[J] > T) - J--; - } - if (X[L] === T) - swap(X, L, J); - else { - J++; - swap(X, J, R); - } - if (J <= K) - L = J + 1; - if (K <= J) - R = J - 1; - } -} -function swap(arr, i, j) { - const temp = arr[i]; - arr[i] = arr[j]; - arr[j] = temp; -} -export default function findMedian(arr) { - const n = arr.length; - const k = Math.floor(n / 2); - SELECT(arr, 0, n - 1, k); - if (n % 2 === 0) { - SELECT(arr, 0, n - 1, k - 1); - return (arr[k - 1] + arr[k]) / 2; - } - else { - return arr[k]; - } -} diff --git a/dist/index.d.ts b/dist/index.d.ts deleted file mode 100644 index e2d358e..0000000 --- a/dist/index.d.ts +++ /dev/null @@ -1 +0,0 @@ -export default function findMedian(arr: number[]): number; diff --git a/dist/index.js b/dist/index.js deleted file mode 100644 index 7bed6e8..0000000 --- a/dist/index.js +++ /dev/null @@ -1,56 +0,0 @@ -function SELECT(X, L, R, K) { - while (R > L) { - if (R - L > 600) { - const N = R - L + 1; - const I = K - L + 1; - const Z = Math.log(N); - const S = 0.5 * Math.exp((2 * Z) / 3); - const SD = 0.5 * Math.sqrt((Z * S * (N - S)) / N) * Math.sign(I - N / 2); - const LL = Math.max(L, Math.floor(K - (I * S) / N + SD)); - const RR = Math.min(R, Math.floor(K + ((N - I) * S) / N + SD)); - SELECT(X, LL, RR, K); - } - const T = X[K]; - let I = L; - let J = R; - swap(X, L, K); - if (X[R] > T) - swap(X, R, L); - while (I < J) { - swap(X, I, J); - I++; - J--; - while (X[I] < T) - I++; - while (X[J] > T) - J--; - } - if (X[L] === T) - swap(X, L, J); - else { - J++; - swap(X, J, R); - } - if (J <= K) - L = J + 1; - if (K <= J) - R = J - 1; - } -} -function swap(arr, i, j) { - const temp = arr[i]; - arr[i] = arr[j]; - arr[j] = temp; -} -export default function findMedian(arr) { - const n = arr.length; - const k = Math.floor(n / 2); - SELECT(arr, 0, n - 1, k); - if (n % 2 === 0) { - SELECT(arr, 0, n - 1, k - 1); - return (arr[k - 1] + arr[k]) / 2; - } - else { - return arr[k]; - } -} diff --git a/dist/index.min.js b/dist/index.min.js deleted file mode 100644 index 8255a8a..0000000 --- a/dist/index.min.js +++ /dev/null @@ -1 +0,0 @@ -function SELECT(X,L,R,K){while(R>L){if(R-L>600){const N=R-L+1;const I=K-L+1;const Z=Math.log(N);const S=.5*Math.exp(2*Z/3);const SD=.5*Math.sqrt(Z*S*(N-S)/N)*Math.sign(I-N/2);const LL=Math.max(L,Math.floor(K-I*S/N+SD));const RR=Math.min(R,Math.floor(K+(N-I)*S/N+SD));SELECT(X,LL,RR,K)}const T=X[K];let I=L;let J=R;swap(X,L,K);if(X[R]>T)swap(X,R,L);while(IT)J--}if(X[L]===T)swap(X,L,J);else{J++;swap(X,J,R)}if(J<=K)L=J+1;if(K<=J)R=J-1}}function swap(arr,i,j){const temp=arr[i];arr[i]=arr[j];arr[j]=temp}export default function findMedian(arr){const n=arr.length;const k=Math.floor(n/2);SELECT(arr,0,n-1,k);if(n%2===0){SELECT(arr,0,n-1,k-1);return(arr[k-1]+arr[k])/2}else{return arr[k]}} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 8527a22..9120b96 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,27 +1,133 @@ { "name": "quick-median", - "version": "1.0.0", + "version": "1.0.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "quick-median", - "version": "1.0.0", - "license": "ISC", - "dependencies": { - "faster-median": "^1.0.0" - }, + "version": "1.0.5", + "license": "MIT", "devDependencies": { "benchmark": "^2.1.4", "chai": "^5.1.1", "compute-median": "^2.0.0", "fast-median": "^1.1.0", + "faster-median": "^1.0.0", "median": "^0.0.2", "median-average": "^1.0.1", "median-quickselect": "^1.0.1", "ml-array-median": "^1.1.6", "mocha": "^10.7.3", - "stats-median": "^1.0.1" + "rimraf": "^6.0.1", + "stats-median": "^1.0.1", + "typescript": "^5.5.4" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" } }, "node_modules/ansi-colors": { @@ -270,6 +376,20 @@ "validate.io-object": "^1.0.3" } }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/debug": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", @@ -323,6 +443,12 @@ "node": ">=0.3.1" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -376,6 +502,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/faster-median/-/faster-median-1.0.0.tgz", "integrity": "sha512-EAjGGpEa0qqwihtu1z51E+FvnVC8gDJy7JyGLgZi4UH3dCMQuQNEIHtpLDqeqeCPA36zKcYCYqE79ZGL/kMTSA==", + "dev": true, "dependencies": { "preciso": "^0.5.0" } @@ -417,6 +544,22 @@ "flat": "cli.js" } }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -606,6 +749,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/jackspeak": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.1.tgz", + "integrity": "sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -697,6 +864,15 @@ "get-func-name": "^2.0.1" } }, + "node_modules/lru-cache": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.0.tgz", + "integrity": "sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==", + "dev": true, + "engines": { + "node": "20 || >=22" + } + }, "node_modules/mean-average": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/mean-average/-/mean-average-1.0.0.tgz", @@ -746,6 +922,15 @@ "node": ">=10" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/ml-array-median": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/ml-array-median/-/ml-array-median-1.1.6.tgz", @@ -857,6 +1042,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -866,6 +1057,31 @@ "node": ">=8" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "dev": true, + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/pathval": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", @@ -896,7 +1112,8 @@ "node_modules/preciso": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/preciso/-/preciso-0.5.0.tgz", - "integrity": "sha512-t/DKHG7hVuhGYYQHOykZrhXdDhDuHsGtkzJgYofdTmxI6AgU60+wTwmT7nv+qFkpGnXr0KugZ1V3+2hTmhNkcg==" + "integrity": "sha512-t/DKHG7hVuhGYYQHOykZrhXdDhDuHsGtkzJgYofdTmxI6AgU60+wTwmT7nv+qFkpGnXr0KugZ1V3+2hTmhNkcg==", + "dev": true }, "node_modules/randombytes": { "version": "2.1.0", @@ -928,6 +1145,63 @@ "node": ">=0.10.0" } }, + "node_modules/rimraf": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", + "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", + "dev": true, + "dependencies": { + "glob": "^11.0.0", + "package-json-from-dist": "^1.0.0" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", + "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -957,6 +1231,39 @@ "randombytes": "^2.1.0" } }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/stats-median": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/stats-median/-/stats-median-1.0.1.tgz", @@ -977,6 +1284,21 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -989,6 +1311,19 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -1037,6 +1372,19 @@ "node": ">=10" } }, + "node_modules/typescript": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/validate.io-array": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/validate.io-array/-/validate.io-array-1.0.6.tgz", @@ -1064,6 +1412,21 @@ "validate.io-array": "^1.0.1" } }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/workerpool": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", @@ -1087,6 +1450,24 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/package.json b/package.json index 16ed71a..e3d917a 100644 --- a/package.json +++ b/package.json @@ -1,25 +1,29 @@ { "name": "quick-median", - "version": "1.0.4", + "version": "1.0.7", "description": "Lightning-fast median finding with O(n) average time complexity using Floyd-Rivest algorithm", - "type": "module", - "main": "dist/index.js", - "types": "dist/index.d.ts", - "module": "./dist/esm/index.js", + "main": "./dist/cjs/index.js", + "types": "./dist/types/index.d.ts", + "module": "./dist/esm/index.mjs", "exports": { ".": { - "import": "./dist/esm/index.js", - "require": "./dist/cjs/index.js" + "require": "./dist/cjs/index.js", + "import": "./dist/esm/index.mjs" } }, + "files": [ + "dist" + ], "scripts": { "test": "mocha", "benchmark": "node benchmark/benchmark.js", "minify": "terser dist/index.js -o dist/index.min.js", - "build": "npm run build:esm && npm run build:cjs", - "build:esm": "tsc", "build:cjs": "tsc -p tsconfig.cjs.json", - "prepublishOnly": "npm run build && npm run minify" + "build:esm": "tsc -p tsconfig.esm.json && npm run rename:esm", + "build": "npm run build:cjs && npm run build:esm", + "clean": "rimraf dist", + "rename:esm": "/bin/zsh ./scripts/fix-mjs.sh", + "prepack": "npm run clean && npm run build" }, "keywords": [ "median", @@ -44,16 +48,17 @@ "chai": "^5.1.1", "compute-median": "^2.0.0", "fast-median": "^1.1.0", + "faster-median": "^1.0.0", "median": "^0.0.2", "median-average": "^1.0.1", "median-quickselect": "^1.0.1", "ml-array-median": "^1.1.6", "mocha": "^10.7.3", + "rimraf": "^6.0.1", "stats-median": "^1.0.1", - "faster-median": "^1.0.0" + "typescript": "^5.5.4" }, "publishConfig": { "access": "public" - }, - "dependencies": {} + } } diff --git a/scripts/fix-mjs.sh b/scripts/fix-mjs.sh new file mode 100644 index 0000000..18494ef --- /dev/null +++ b/scripts/fix-mjs.sh @@ -0,0 +1,6 @@ +for file in ./dist/esm/*.js; do + echo "Updating $file contents..." + sed -i '' "s/\.js'/\.mjs'/g" "$file" + echo "Renaming $file to ${file%.js}.mjs..." + mv "$file" "${file%.js}.mjs" +done \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 02ab205..0b379c4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -43,7 +43,7 @@ function swap(arr: number[], i: number, j: number): void { arr[j] = temp; } -export default function findMedian(arr: number[]): number { +export function findMedian(arr: number[]): number { const n = arr.length; const k = Math.floor(n / 2); SELECT(arr, 0, n - 1, k); @@ -55,3 +55,5 @@ export default function findMedian(arr: number[]): number { return arr[k]; } } + +export default findMedian; diff --git a/tsconfig.base.json b/tsconfig.base.json new file mode 100644 index 0000000..a3f257f --- /dev/null +++ b/tsconfig.base.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "lib": ["esnext"], + "declaration": true, + "declarationDir": "./dist/types", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "node", + "baseUrl": ".", + "rootDir": "./src" + }, + "include": ["src"], + "exclude": ["dist", "node_modules"] +} diff --git a/tsconfig.cjs.json b/tsconfig.cjs.json index 44b9028..2dab503 100644 --- a/tsconfig.cjs.json +++ b/tsconfig.cjs.json @@ -1,7 +1,8 @@ { - "extends": "./tsconfig.json", + "extends": "./tsconfig.base.json", "compilerOptions": { "module": "commonjs", - "outDir": "./dist/cjs" + "outDir": "./dist/cjs", + "target": "ES2015" } } diff --git a/tsconfig.esm.json b/tsconfig.esm.json new file mode 100644 index 0000000..a5a0a0c --- /dev/null +++ b/tsconfig.esm.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.base.json", + "compilerOptions": { + "module": "esnext", + "outDir": "./dist/esm", + "target": "esnext" + } +} diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index 2ba155d..0000000 --- a/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "compilerOptions": { - "target": "es2020", - "module": "es2020", - "moduleResolution": "node", - "declaration": true, - "outDir": "./dist/esm", - "strict": true, - "esModuleInterop": true - }, - "include": ["src"], - "exclude": ["node_modules", "**/__tests__/*"] -} diff --git a/tsconfig.types.json b/tsconfig.types.json new file mode 100644 index 0000000..bf11a62 --- /dev/null +++ b/tsconfig.types.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.base.json", + "compilerOptions": { + "declaration": true, + "emitDeclarationOnly": true, + "outDir": "./dist/types" + } +}