diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d87d4f..aeb1c59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,3 +16,7 @@ - Fixed ESM wrapping issue. - Implemented code splitting. + +## Version 0.0.5 + +- Added `bozoSort`. diff --git a/README.md b/README.md index be3ffc2..cc407f4 100644 --- a/README.md +++ b/README.md @@ -118,11 +118,25 @@ largest element. **Time complexity (best, average and worse):** $O(n + k)$, where $k$ is the range of input (maximum element - minimum element + 1). +- `function bozoSort(array: T[]): T[];` Sorts an array using the Bozo Sort algorithm. + + | Name | Description | + | ------- | ----------------------- | + | `array` | The array to be sorted. | + +- `function bozoSort(array: T[], opts: SortingOptions): T[];` + Sorts an array using the Bozo Sort algorithm. + + | Name | Description | + | ------- | ------------------------------------- | + | `array` | The array to be sorted. | + | `opts` | An object containing sorting options. | + ## Usage ```typescript -import { mergeSort } from '@santi100/sorting-lib'; // ESM -const { mergeSort } = require('@santi100/sorting-lib'); // CJS +import { mergeSort, bozoSort } from '@santi100/sorting-lib'; // ESM +const { mergeSort, bozoSort } = require('@santi100/sorting-lib'); // CJS const sorted = mergeSort([4, 2, 5, 1, 3]); // sorted = [1, 2, 3, 4, 5] const descendingSorted = mergeSort([4, 2, 5, 1, 3], { order: 'descending' }); // descendingSorted = [5, 4, 3, 2, 1] const objSorted = mergeSort( @@ -141,6 +155,8 @@ const objSorted = mergeSort( ); // returns [ { age: 12 }, { age: 23 }, { age: 30 }] // You can do same for all algorithms, except for `radixSort`, which is limited to ints for now, so // its only option is `order`. +const sortedArray = bozoSort(array); +console.log(sortedArray); // Output: [1, 2, 3] ``` ## Contribute diff --git a/cjs/bogo-sort.js b/cjs/bogo-sort.js index 654c6ad..5f91470 100644 --- a/cjs/bogo-sort.js +++ b/cjs/bogo-sort.js @@ -1,50 +1,28 @@ -'use strict'; -var __spreadArray = - (this && this.__spreadArray) || - function (to, from, pack) { - if (pack || arguments.length === 2) - for (var i = 0, l = from.length, ar; i < l; i++) { - if (ar || !(i in from)) { - if (!ar) ar = Array.prototype.slice.call(from, 0, i); - ar[i] = from[i]; - } - } - return to.concat(ar || Array.prototype.slice.call(from)); - }; -var assertDefined = require('@santi100/assertion-lib/cjs/defined'); -var assertInstanceOf = require('@santi100/assertion-lib/cjs/instance-of'); -var assertOneOf = require('@santi100/assertion-lib/cjs/one-of'); -var assertTypeOf = require('@santi100/assertion-lib/cjs/type-of'); -var shuffle = require('@santi100/array-shuffle'); -var core_1 = require('./core'); +"use strict"; +var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +}; +var assertDefined = require("@santi100/assertion-lib/cjs/defined"); +var assertInstanceOf = require("@santi100/assertion-lib/cjs/instance-of"); +var assertOneOf = require("@santi100/assertion-lib/cjs/one-of"); +var assertTypeOf = require("@santi100/assertion-lib/cjs/type-of"); +var shuffle = require("@santi100/array-shuffle"); +var core_1 = require("./core"); module.exports = function bogoSort(arr, opts) { - if (opts === void 0) { - opts = {}; - } - assertInstanceOf(arr, Array, 'arr'); - assertDefined(opts, 'opts'); - assertTypeOf(opts, 'object'); - var _a = opts.order, - order = _a === void 0 ? 'ascending' : _a, - _b = opts.comparator, - comparator = - _b === void 0 - ? order === 'ascending' - ? core_1.__defAscending - : core_1.__defDescending - : _b; - assertOneOf(order, 'opts.order', ['ascending', 'descending']); - function __isSorted(arr) { - var array = __spreadArray([], arr, true); - var sorted = true; - for (var i = 0; i < array.length - 1; i++) { - if (comparator(array[i + 1], array[i]) < 0) { - sorted = false; - } - } - return sorted; - } - var array = __spreadArray([], arr, true); - while (!__isSorted(array)) array = shuffle(array); - return array; + if (opts === void 0) { opts = {}; } + assertInstanceOf(arr, Array, 'arr'); + assertDefined(opts, 'opts'); + assertTypeOf(opts, 'object'); + var _a = opts.order, order = _a === void 0 ? 'ascending' : _a, _b = opts.comparator, comparator = _b === void 0 ? order === 'ascending' ? core_1.__defAscending : core_1.__defDescending : _b; + assertOneOf(order, 'opts.order', ['ascending', 'descending']); + var array = __spreadArray([], arr, true); + while (!(0, core_1.__isSorted)(array, comparator)) + array = shuffle(array); + return array; }; diff --git a/cjs/bozo-sort.d.ts b/cjs/bozo-sort.d.ts new file mode 100644 index 0000000..4e60055 --- /dev/null +++ b/cjs/bozo-sort.d.ts @@ -0,0 +1,17 @@ +import { SortOptions } from './core'; +/** + * Sorts an array using the Bozo Sort algorithm. + * + * @template T The type of elements in the array. + * @param {T[]} array The array to be sorted. + */ +declare function bozoSort(array: T[]): T[]; +/** + * Sorts an array using the Bozo Sort algorithm. + * + * @template T The type of elements in the array. + * @param {T[]} array The array to be sorted. + * @param {SortOptions} [opts] An object containing sorting options. + */ +declare function bozoSort(array: T[], opts: SortOptions): T[]; +export = bozoSort; diff --git a/cjs/bozo-sort.js b/cjs/bozo-sort.js new file mode 100644 index 0000000..92e9be0 --- /dev/null +++ b/cjs/bozo-sort.js @@ -0,0 +1,37 @@ +"use strict"; +var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +}; +var core_1 = require("./core"); +var randomIntegers = require("@santi100/random-lib/cjs/random-integers"); +var assertArray = require("@santi100/assertion-lib/cjs/array"); +var assertDefined = require("@santi100/assertion-lib/cjs/defined"); +var assertTypeOf = require("@santi100/assertion-lib/cjs/type-of"); +var assertOneOf = require("@santi100/assertion-lib/cjs/one-of"); +function bozoSort(array, opts) { + var _a; + if (opts === void 0) { opts = { + order: 'ascending', + comparator: core_1.__defAscending + }; } + var arr = __spreadArray([], array, true); + assertArray(array, 'array'); + assertDefined(opts, 'opts'); + assertTypeOf(opts, 'object', 'opts'); + var _b = opts.order, order = _b === void 0 ? 'ascending' : _b, _c = opts.comparator, comparator = _c === void 0 ? order === 'ascending' ? core_1.__defAscending : core_1.__defDescending : _c; + assertTypeOf(order, 'string', 'order'); + assertOneOf(order, 'order', ['ascending', 'descending']); + assertTypeOf(comparator, 'function', 'comparator'); + while (!(0, core_1.__isSorted)(arr, comparator)) { + var _d = randomIntegers(2, { max: array.length, min: 0 }), i = _d[0], j = _d[1]; + _a = [arr[j], arr[i]], arr[i] = _a[0], arr[j] = _a[1]; // swap + } + return arr; +} +module.exports = bozoSort; diff --git a/cjs/bubble-sort.js b/cjs/bubble-sort.js index a7712e9..32018a8 100644 --- a/cjs/bubble-sort.js +++ b/cjs/bubble-sort.js @@ -1,35 +1,25 @@ -'use strict'; -var assertDefined = require('@santi100/assertion-lib/cjs/defined'); -var assertInstanceOf = require('@santi100/assertion-lib/cjs/instance-of'); -var assertOneOf = require('@santi100/assertion-lib/cjs/one-of'); -var assertTypeOf = require('@santi100/assertion-lib/cjs/type-of'); -var core_1 = require('./core'); +"use strict"; +var assertDefined = require("@santi100/assertion-lib/cjs/defined"); +var assertInstanceOf = require("@santi100/assertion-lib/cjs/instance-of"); +var assertOneOf = require("@santi100/assertion-lib/cjs/one-of"); +var assertTypeOf = require("@santi100/assertion-lib/cjs/type-of"); +var core_1 = require("./core"); module.exports = function bubbleSort(arr, opts) { - if (opts === void 0) { - opts = {}; - } - assertInstanceOf(arr, Array, 'arr'); - assertDefined(opts, 'opts'); - assertTypeOf(opts, 'object'); - var array = arr.slice(); - var _a = opts.order, - order = _a === void 0 ? 'ascending' : _a, - _b = opts.comparator, - comparator = - _b === void 0 - ? order === 'ascending' - ? core_1.__defAscending - : core_1.__defDescending - : _b; - assertOneOf(order, 'opts.order', ['ascending', 'descending']); - for (var i = 0; i < array.length; i++) { - for (var j = 0; j < array.length - i - 1; j++) { - if (comparator(array[j], array[j + 1]) > 0) { - var temp = array[j]; - array[j] = array[j + 1]; - array[j + 1] = temp; - } - } - } - return array; + if (opts === void 0) { opts = {}; } + assertInstanceOf(arr, Array, 'arr'); + assertDefined(opts, 'opts'); + assertTypeOf(opts, 'object'); + var array = arr.slice(); + var _a = opts.order, order = _a === void 0 ? 'ascending' : _a, _b = opts.comparator, comparator = _b === void 0 ? order === 'ascending' ? core_1.__defAscending : core_1.__defDescending : _b; + assertOneOf(order, 'opts.order', ['ascending', 'descending']); + for (var i = 0; i < array.length; i++) { + for (var j = 0; j < array.length - i - 1; j++) { + if (comparator(array[j], array[j + 1]) > 0) { + var temp = array[j]; + array[j] = array[j + 1]; + array[j + 1] = temp; + } + } + } + return array; }; diff --git a/cjs/core.d.ts b/cjs/core.d.ts index ebf6c2f..999af0f 100644 --- a/cjs/core.d.ts +++ b/cjs/core.d.ts @@ -12,29 +12,29 @@ export type SortOrder = 'ascending' | 'descending'; * See {@link RadixSortOptions} for the options specific to it. */ export interface SortOptions { - /** - * Comparator function for every sorting algorithm, except for {@link radixSort}. - * It's fully compatible with {@link Array.prototype.sort}'s callback. See {@link SortComparator}. - * - * **Keep in mind this option overrides the `order` option.** - */ - comparator?: SortComparator; - /** - * Sorting order string. Must be either `ascending` or `descending`. See {@link SortOrder}. - */ - order?: SortOrder; + /** + * Comparator function for every sorting algorithm, except for {@link radixSort}. + * It's fully compatible with {@link Array.prototype.sort}'s callback. See {@link SortComparator}. + * + * **Keep in mind this option overrides the `order` option.** + */ + comparator?: SortComparator; + /** + * Sorting order string. Must be either `ascending` or `descending`. See {@link SortOrder}. + */ + order?: SortOrder; } /** * Shape of the `opts` object exclusive to {@link radixSort}. */ export interface RadixSortOptions { - /** - * Sorting order string. Must be either `ascending` or `descending`. See {@link SortOrder}. - */ - order?: SortOrder; + /** + * Sorting order string. Must be either `ascending` or `descending`. See {@link SortOrder}. + */ + order?: SortOrder; } /** - * Shape of the `opts` object exclusive to {@link countingSort}. + * Shape of the `opts` object exclusive to `countingSort`. * @since 0.0.3 */ export type CountingSortOptions = RadixSortOptions; @@ -42,3 +42,4 @@ export declare function __defAscending(a: unknown, b: unknown): 1 | -1 | 0; export declare function __reverse(arr: T[]): T[]; export declare function __defDescending(a: unknown, b: unknown): 1 | -1 | 0; export declare function __isInteger(num: number): boolean; +export declare function __isSorted(arr: T[], comparator: SortComparator): boolean; diff --git a/cjs/core.js b/cjs/core.js index 5de8f70..d8b4afc 100644 --- a/cjs/core.js +++ b/cjs/core.js @@ -1,38 +1,53 @@ -'use strict'; +"use strict"; +var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +}; exports.__esModule = true; -exports.__isInteger = - exports.__defDescending = - exports.__reverse = - exports.__defAscending = - void 0; +exports.__isSorted = exports.__isInteger = exports.__defDescending = exports.__reverse = exports.__defAscending = void 0; function __defAscending(a, b) { - // @ts-expect-error It's fine to have "unknown". - if (a < b) return -1; - // @ts-expect-error It's fine to have "unknown". - if (a > b) return 1; - return 0; + // @ts-expect-error It's fine to have "unknown". + if (a < b) + return -1; + // @ts-expect-error It's fine to have "unknown". + if (a > b) + return 1; + return 0; } exports.__defAscending = __defAscending; function __reverse(arr) { - return arr.slice().reverse(); + return arr.slice().reverse(); } exports.__reverse = __reverse; function __defDescending(a, b) { - // @ts-expect-error It's fine to have "unknown". - if (a < b) return 1; - // @ts-expect-error It's fine to have "unknown". - if (a > b) return -1; - return 0; + // @ts-expect-error It's fine to have "unknown". + if (a < b) + return 1; + // @ts-expect-error It's fine to have "unknown". + if (a > b) + return -1; + return 0; } exports.__defDescending = __defDescending; function __isInteger(num) { - var _a; - return ( - ((_a = Number === null || Number === void 0 ? void 0 : Number.isInteger) === - null || _a === void 0 - ? void 0 - : _a.call(Number, num)) || - (num < 0 ? Math.ceil(num) : Math.floor(num)) === num - ); + var _a; + return (((_a = Number === null || Number === void 0 ? void 0 : Number.isInteger) === null || _a === void 0 ? void 0 : _a.call(Number, num)) || + (num < 0 ? Math.ceil(num) : Math.floor(num)) === num); } exports.__isInteger = __isInteger; +function __isSorted(arr, comparator) { + var array = __spreadArray([], arr, true); + var sorted = true; + for (var i = 0; i < array.length - 1; i++) { + if (comparator(array[i + 1], array[i]) < 0) { + sorted = false; + } + } + return sorted; +} +exports.__isSorted = __isSorted; diff --git a/cjs/counting-sort.js b/cjs/counting-sort.js index 3b857bf..353d8d5 100644 --- a/cjs/counting-sort.js +++ b/cjs/counting-sort.js @@ -1,55 +1,50 @@ -'use strict'; -var __spreadArray = - (this && this.__spreadArray) || - function (to, from, pack) { - if (pack || arguments.length === 2) - for (var i = 0, l = from.length, ar; i < l; i++) { - if (ar || !(i in from)) { - if (!ar) ar = Array.prototype.slice.call(from, 0, i); - ar[i] = from[i]; - } - } - return to.concat(ar || Array.prototype.slice.call(from)); - }; -var assertDefined = require('@santi100/assertion-lib/cjs/defined'); -var assertInstanceOf = require('@santi100/assertion-lib/cjs/instance-of'); -var assertOneOf = require('@santi100/assertion-lib/cjs/one-of'); -var assertTypeOf = require('@santi100/assertion-lib/cjs/type-of'); +"use strict"; +var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +}; +var assertDefined = require("@santi100/assertion-lib/cjs/defined"); +var assertInstanceOf = require("@santi100/assertion-lib/cjs/instance-of"); +var assertOneOf = require("@santi100/assertion-lib/cjs/one-of"); +var assertTypeOf = require("@santi100/assertion-lib/cjs/type-of"); module.exports = function countingSort(arr, opts) { - if (opts === void 0) { - opts = {}; - } - assertInstanceOf(arr, Array, 'arr'); - assertDefined(opts, 'opts'); - assertTypeOf(opts, 'object'); - var array = __spreadArray([], arr, true); - var _a = opts.order, - order = _a === void 0 ? 'ascending' : _a; - assertOneOf(order, 'opts.order', ['ascending', 'descending']); - if (array.length === 0) return []; - var max = Math.max.apply(Math, array); - for (var _i = 0, array_1 = array; _i < array_1.length; _i++) { - var element = array_1[_i]; - assertTypeOf(element, 'number', 'arr['.concat(arr.indexOf(element), ']')); - } - var countingArray = Array(max + 1).fill(0); - // Step 1: populate the counting array - for (var _b = 0, array_2 = array; _b < array_2.length; _b++) { - var element = array_2[_b]; - countingArray[element]++; - } - // Step 2: modify the counting array to store the actual position of each element in the sorted array - for (var i = 1; i <= max; i++) { - countingArray[i] += countingArray[i - 1]; - } - // Step 3: Traverse the input array and place the elements in the sorted array - var sortedArray = Array(array.length); - for (var i = array.length - 1; i >= 0; i--) { - var element = array[i]; - var position = countingArray[element] - 1; - sortedArray[position] = element; - countingArray[element]--; - } - // Step 4: Return the sorted array in the specified order - return order === 'ascending' ? sortedArray : sortedArray.slice().reverse(); + if (opts === void 0) { opts = {}; } + assertInstanceOf(arr, Array, 'arr'); + assertDefined(opts, 'opts'); + assertTypeOf(opts, 'object'); + var array = __spreadArray([], arr, true); + var _a = opts.order, order = _a === void 0 ? 'ascending' : _a; + assertOneOf(order, 'opts.order', ['ascending', 'descending']); + if (array.length === 0) + return []; + var max = Math.max.apply(Math, array); + for (var _i = 0, array_1 = array; _i < array_1.length; _i++) { + var element = array_1[_i]; + assertTypeOf(element, 'number', "arr[".concat(arr.indexOf(element), "]")); + } + var countingArray = Array(max + 1).fill(0); + // Step 1: populate the counting array + for (var _b = 0, array_2 = array; _b < array_2.length; _b++) { + var element = array_2[_b]; + countingArray[element]++; + } + // Step 2: modify the counting array to store the actual position of each element in the sorted array + for (var i = 1; i <= max; i++) { + countingArray[i] += countingArray[i - 1]; + } + // Step 3: Traverse the input array and place the elements in the sorted array + var sortedArray = Array(array.length); + for (var i = array.length - 1; i >= 0; i--) { + var element = array[i]; + var position = countingArray[element] - 1; + sortedArray[position] = element; + countingArray[element]--; + } + // Step 4: Return the sorted array in the specified order + return order === 'ascending' ? sortedArray : sortedArray.slice().reverse(); }; diff --git a/cjs/heap-sort.js b/cjs/heap-sort.js index cc40fb3..d0130d0 100644 --- a/cjs/heap-sort.js +++ b/cjs/heap-sort.js @@ -1,54 +1,49 @@ -'use strict'; -var assertDefined = require('@santi100/assertion-lib/cjs/defined'); -var assertInstanceOf = require('@santi100/assertion-lib/cjs/instance-of'); -var assertOneOf = require('@santi100/assertion-lib/cjs/one-of'); -var assertTypeOf = require('@santi100/assertion-lib/cjs/type-of'); -var core_1 = require('./core'); +"use strict"; +var assertDefined = require("@santi100/assertion-lib/cjs/defined"); +var assertInstanceOf = require("@santi100/assertion-lib/cjs/instance-of"); +var assertOneOf = require("@santi100/assertion-lib/cjs/one-of"); +var assertTypeOf = require("@santi100/assertion-lib/cjs/type-of"); +var core_1 = require("./core"); module.exports = function heapSort(arr, opts) { - if (opts === void 0) { - opts = { comparator: core_1.__defAscending, order: 'ascending' }; - } - assertInstanceOf(arr, Array, 'arr'); - assertDefined(opts, 'opts'); - assertTypeOf(opts, 'object'); - var _a = opts.comparator, - comparator = _a === void 0 ? core_1.__defAscending : _a, - _b = opts.order, - order = _b === void 0 ? 'ascending' : _b; - var n = arr.length; - assertOneOf(order, 'opts.order', ['ascending', 'descending']); - // build heap - for (var i = Math.floor(n / 2) - 1; i >= 0; i--) { - __heapify(arr, i, n, comparator, order); - } - // extract elements from heap - for (var i = n - 1; i > 0; i--) { - __swap(arr, 0, i); - __heapify(arr, 0, i, comparator, order); - } - function compare(a, b, comparator, order) { - var cmp = comparator(a, b); - return order === 'ascending' ? cmp : -cmp; - } - function __swap(arr, i, j) { - var tmp = arr[i]; - arr[i] = arr[j]; - arr[j] = tmp; - } - function __heapify(arr, i, n, comparator, order) { - var largest = i; - var left = 2 * i + 1; - var right = 2 * i + 2; - if (left < n && compare(arr[left], arr[largest], comparator, order) > 0) { - largest = left; - } - if (right < n && compare(arr[right], arr[largest], comparator, order) > 0) { - largest = right; - } - if (largest !== i) { - __swap(arr, i, largest); - __heapify(arr, largest, n, comparator, order); - } - } - return arr; + if (opts === void 0) { opts = { comparator: core_1.__defAscending, order: 'ascending' }; } + assertInstanceOf(arr, Array, 'arr'); + assertDefined(opts, 'opts'); + assertTypeOf(opts, 'object'); + var _a = opts.comparator, comparator = _a === void 0 ? core_1.__defAscending : _a, _b = opts.order, order = _b === void 0 ? 'ascending' : _b; + var n = arr.length; + assertOneOf(order, 'opts.order', ['ascending', 'descending']); + // build heap + for (var i = Math.floor(n / 2) - 1; i >= 0; i--) { + __heapify(arr, i, n, comparator, order); + } + // extract elements from heap + for (var i = n - 1; i > 0; i--) { + __swap(arr, 0, i); + __heapify(arr, 0, i, comparator, order); + } + function compare(a, b, comparator, order) { + var cmp = comparator(a, b); + return order === 'ascending' ? cmp : -cmp; + } + function __swap(arr, i, j) { + var tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + } + function __heapify(arr, i, n, comparator, order) { + var largest = i; + var left = 2 * i + 1; + var right = 2 * i + 2; + if (left < n && compare(arr[left], arr[largest], comparator, order) > 0) { + largest = left; + } + if (right < n && compare(arr[right], arr[largest], comparator, order) > 0) { + largest = right; + } + if (largest !== i) { + __swap(arr, i, largest); + __heapify(arr, largest, n, comparator, order); + } + } + return arr; }; diff --git a/cjs/index.d.ts b/cjs/index.d.ts index 0d673d2..d64c02d 100644 --- a/cjs/index.d.ts +++ b/cjs/index.d.ts @@ -1,4 +1,5 @@ import bogoSort = require('./bogo-sort'); +import bozoSort = require('./bozo-sort'); import bubbleSort = require('./bubble-sort'); import countingSort = require('./counting-sort'); import heapSort = require('./heap-sort'); @@ -8,15 +9,4 @@ import quickSort = require('./quick-sort'); import radixSort = require('./radix-sort'); import selectionSort = require('./selection-sort'); import shellSort = require('./shell-sort'); -export { - bogoSort, - bubbleSort, - countingSort, - heapSort, - insertionSort, - mergeSort, - quickSort, - radixSort, - selectionSort, - shellSort -}; +export { bogoSort, bozoSort, bubbleSort, countingSort, heapSort, insertionSort, mergeSort, quickSort, radixSort, selectionSort, shellSort, }; diff --git a/cjs/index.js b/cjs/index.js index e222c84..b8a4a95 100644 --- a/cjs/index.js +++ b/cjs/index.js @@ -1,33 +1,25 @@ -'use strict'; +"use strict"; exports.__esModule = true; -exports.shellSort = - exports.selectionSort = - exports.radixSort = - exports.quickSort = - exports.mergeSort = - exports.insertionSort = - exports.heapSort = - exports.countingSort = - exports.bubbleSort = - exports.bogoSort = - void 0; -var bogoSort = require('./bogo-sort'); +exports.shellSort = exports.selectionSort = exports.radixSort = exports.quickSort = exports.mergeSort = exports.insertionSort = exports.heapSort = exports.countingSort = exports.bubbleSort = exports.bozoSort = exports.bogoSort = void 0; +var bogoSort = require("./bogo-sort"); exports.bogoSort = bogoSort; -var bubbleSort = require('./bubble-sort'); +var bozoSort = require("./bozo-sort"); +exports.bozoSort = bozoSort; +var bubbleSort = require("./bubble-sort"); exports.bubbleSort = bubbleSort; -var countingSort = require('./counting-sort'); +var countingSort = require("./counting-sort"); exports.countingSort = countingSort; -var heapSort = require('./heap-sort'); +var heapSort = require("./heap-sort"); exports.heapSort = heapSort; -var insertionSort = require('./insertion-sort'); +var insertionSort = require("./insertion-sort"); exports.insertionSort = insertionSort; -var mergeSort = require('./merge-sort'); +var mergeSort = require("./merge-sort"); exports.mergeSort = mergeSort; -var quickSort = require('./quick-sort'); +var quickSort = require("./quick-sort"); exports.quickSort = quickSort; -var radixSort = require('./radix-sort'); +var radixSort = require("./radix-sort"); exports.radixSort = radixSort; -var selectionSort = require('./selection-sort'); +var selectionSort = require("./selection-sort"); exports.selectionSort = selectionSort; -var shellSort = require('./shell-sort'); +var shellSort = require("./shell-sort"); exports.shellSort = shellSort; diff --git a/cjs/insertion-sort.js b/cjs/insertion-sort.js index 5875690..c53d0c0 100644 --- a/cjs/insertion-sort.js +++ b/cjs/insertion-sort.js @@ -1,48 +1,35 @@ -'use strict'; -var __spreadArray = - (this && this.__spreadArray) || - function (to, from, pack) { - if (pack || arguments.length === 2) - for (var i = 0, l = from.length, ar; i < l; i++) { - if (ar || !(i in from)) { - if (!ar) ar = Array.prototype.slice.call(from, 0, i); - ar[i] = from[i]; - } - } - return to.concat(ar || Array.prototype.slice.call(from)); - }; -var assertDefined = require('@santi100/assertion-lib/cjs/defined'); -var assertInstanceOf = require('@santi100/assertion-lib/cjs/instance-of'); -var assertOneOf = require('@santi100/assertion-lib/cjs/one-of'); -var assertTypeOf = require('@santi100/assertion-lib/cjs/type-of'); -var core_1 = require('./core'); +"use strict"; +var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +}; +var assertDefined = require("@santi100/assertion-lib/cjs/defined"); +var assertInstanceOf = require("@santi100/assertion-lib/cjs/instance-of"); +var assertOneOf = require("@santi100/assertion-lib/cjs/one-of"); +var assertTypeOf = require("@santi100/assertion-lib/cjs/type-of"); +var core_1 = require("./core"); module.exports = function insertionSort(arr, opts) { - if (opts === void 0) { - opts = {}; - } - assertInstanceOf(arr, Array, 'arr'); - assertDefined(opts, 'opts'); - assertTypeOf(opts, 'object'); - var array = __spreadArray([], arr, true); - var _a = opts.order, - order = _a === void 0 ? 'ascending' : _a, - _b = opts.comparator, - comparator = - _b === void 0 - ? order === 'ascending' - ? core_1.__defAscending - : core_1.__defDescending - : _b; - assertOneOf(order, 'opts.order', ['ascending', 'descending']); - assertTypeOf(comparator, 'function', 'comparator'); - for (var i = 1; i < array.length; i++) { - var current = array[i]; - var j = i - 1; - while (j > -1 && comparator(current, array[j]) < 0) { - array[j + 1] = array[j]; - j--; - } - array[j + 1] = current; - } - return array; + if (opts === void 0) { opts = {}; } + assertInstanceOf(arr, Array, 'arr'); + assertDefined(opts, 'opts'); + assertTypeOf(opts, 'object'); + var array = __spreadArray([], arr, true); + var _a = opts.order, order = _a === void 0 ? 'ascending' : _a, _b = opts.comparator, comparator = _b === void 0 ? order === 'ascending' ? core_1.__defAscending : core_1.__defDescending : _b; + assertOneOf(order, 'opts.order', ['ascending', 'descending']); + assertTypeOf(comparator, 'function', 'comparator'); + for (var i = 1; i < array.length; i++) { + var current = array[i]; + var j = i - 1; + while (j > -1 && comparator(current, array[j]) < 0) { + array[j + 1] = array[j]; + j--; + } + array[j + 1] = current; + } + return array; }; diff --git a/cjs/merge-sort.js b/cjs/merge-sort.js index f5cfff2..53a0701 100644 --- a/cjs/merge-sort.js +++ b/cjs/merge-sort.js @@ -1,74 +1,54 @@ -'use strict'; -var __spreadArray = - (this && this.__spreadArray) || - function (to, from, pack) { - if (pack || arguments.length === 2) - for (var i = 0, l = from.length, ar; i < l; i++) { - if (ar || !(i in from)) { - if (!ar) ar = Array.prototype.slice.call(from, 0, i); - ar[i] = from[i]; - } - } - return to.concat(ar || Array.prototype.slice.call(from)); - }; -var assertDefined = require('@santi100/assertion-lib/cjs/defined'); -var assertInstanceOf = require('@santi100/assertion-lib/cjs/instance-of'); -var assertOneOf = require('@santi100/assertion-lib/cjs/one-of'); -var assertTypeOf = require('@santi100/assertion-lib/cjs/type-of'); -var core_1 = require('./core'); +"use strict"; +var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +}; +var assertDefined = require("@santi100/assertion-lib/cjs/defined"); +var assertInstanceOf = require("@santi100/assertion-lib/cjs/instance-of"); +var assertOneOf = require("@santi100/assertion-lib/cjs/one-of"); +var assertTypeOf = require("@santi100/assertion-lib/cjs/type-of"); +var core_1 = require("./core"); function __merge(left, right, comparator) { - var arr = new Array(left.length + right.length); - var i = 0, - j = 0, - k = 0; - while (i < left.length && j < right.length) { - if (comparator(left[i], right[j]) < 0) { - arr[k++] = left[i++]; - } else { - arr[k++] = right[j++]; - } - } - while (i < left.length) { - arr[k++] = left[i++]; - } - while (j < right.length) { - arr[k++] = right[j++]; - } - return arr; + var arr = new Array(left.length + right.length); + var i = 0, j = 0, k = 0; + while (i < left.length && j < right.length) { + if (comparator(left[i], right[j]) < 0) { + arr[k++] = left[i++]; + } + else { + arr[k++] = right[j++]; + } + } + while (i < left.length) { + arr[k++] = left[i++]; + } + while (j < right.length) { + arr[k++] = right[j++]; + } + return arr; } module.exports = function mergeSort(arr, opts) { - if (opts === void 0) { - opts = {}; - } - assertInstanceOf(arr, Array, 'arr'); - assertDefined(opts, 'opts'); - assertTypeOf(opts, 'object'); - var array = __spreadArray([], arr, true); - var _a = opts.order, - order = _a === void 0 ? 'ascending' : _a, - _b = opts.comparator, - comparator = - _b === void 0 - ? order === 'ascending' - ? core_1.__defAscending - : core_1.__defDescending - : _b; - assertOneOf(order, 'opts.order', ['ascending', 'descending']); - for (var size = 1; size < array.length; size *= 2) { - for (var leftStart = 0; leftStart < array.length; leftStart += 2 * size) { - var mid = leftStart + size; - var rightStart = Math.min(leftStart + 2 * size, array.length); - var left = array.slice(leftStart, mid); - var right = array.slice(mid, rightStart); - array.splice.apply( - array, - __spreadArray( - [leftStart, rightStart - leftStart], - __merge(left, right, comparator), - false - ) - ); - } - } - return array; + if (opts === void 0) { opts = {}; } + assertInstanceOf(arr, Array, 'arr'); + assertDefined(opts, 'opts'); + assertTypeOf(opts, 'object'); + var array = __spreadArray([], arr, true); + var _a = opts.order, order = _a === void 0 ? 'ascending' : _a, _b = opts.comparator, comparator = _b === void 0 ? order === 'ascending' ? core_1.__defAscending : core_1.__defDescending : _b; + assertOneOf(order, 'opts.order', ['ascending', 'descending']); + for (var size = 1; size < array.length; size *= 2) { + for (var leftStart = 0; leftStart < array.length; leftStart += 2 * size) { + var mid = leftStart + size; + var rightStart = Math.min(leftStart + 2 * size, array.length); + var left = array.slice(leftStart, mid); + var right = array.slice(mid, rightStart); + array.splice.apply(array, __spreadArray([leftStart, + rightStart - leftStart], __merge(left, right, comparator), false)); + } + } + return array; }; diff --git a/cjs/quick-sort.js b/cjs/quick-sort.js index a11b2ae..27327ef 100644 --- a/cjs/quick-sort.js +++ b/cjs/quick-sort.js @@ -1,66 +1,53 @@ -'use strict'; -var __spreadArray = - (this && this.__spreadArray) || - function (to, from, pack) { - if (pack || arguments.length === 2) - for (var i = 0, l = from.length, ar; i < l; i++) { - if (ar || !(i in from)) { - if (!ar) ar = Array.prototype.slice.call(from, 0, i); - ar[i] = from[i]; - } - } - return to.concat(ar || Array.prototype.slice.call(from)); - }; -var assertDefined = require('@santi100/assertion-lib/cjs/defined'); -var assertInstanceOf = require('@santi100/assertion-lib/cjs/instance-of'); -var assertOneOf = require('@santi100/assertion-lib/cjs/one-of'); -var assertTypeOf = require('@santi100/assertion-lib/cjs/type-of'); -var core_1 = require('./core'); +"use strict"; +var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +}; +var assertDefined = require("@santi100/assertion-lib/cjs/defined"); +var assertInstanceOf = require("@santi100/assertion-lib/cjs/instance-of"); +var assertOneOf = require("@santi100/assertion-lib/cjs/one-of"); +var assertTypeOf = require("@santi100/assertion-lib/cjs/type-of"); +var core_1 = require("./core"); module.exports = function quickSort(arr, opts) { - if (opts === void 0) { - opts = {}; - } - assertInstanceOf(arr, Array, 'arr'); - assertDefined(opts, 'opts'); - assertTypeOf(opts, 'object'); - var array = __spreadArray([], arr, true); - var _a = opts.order, - order = _a === void 0 ? 'ascending' : _a, - _b = opts.comparator, - comparator = - _b === void 0 - ? order === 'ascending' - ? core_1.__defAscending - : core_1.__defDescending - : _b; - assertOneOf(order, 'opts.order', ['ascending', 'descending']); - var stack = [0, array.length - 1]; - while (stack.length > 0) { - var end = stack.pop(); - var start = stack.pop(); - if (start >= end) { - continue; - } - var pivotIndex = __partition(array, start, end); - stack.push(start, pivotIndex - 1); - stack.push(pivotIndex + 1, end); - } - function __partition(arr, start, end) { - function __swap(arr, a, b) { - var temp = arr[a]; - arr[a] = arr[b]; - arr[b] = temp; - } - var pivotValue = arr[end]; - var partitionIndex = start; - for (var i = start; i < end; i++) { - if (comparator(arr[i], pivotValue) < 0) { - __swap(arr, i, partitionIndex); - partitionIndex++; - } - } - __swap(arr, end, partitionIndex); - return partitionIndex; - } - return array; + if (opts === void 0) { opts = {}; } + assertInstanceOf(arr, Array, 'arr'); + assertDefined(opts, 'opts'); + assertTypeOf(opts, 'object'); + var array = __spreadArray([], arr, true); + var _a = opts.order, order = _a === void 0 ? 'ascending' : _a, _b = opts.comparator, comparator = _b === void 0 ? order === 'ascending' ? core_1.__defAscending : core_1.__defDescending : _b; + assertOneOf(order, 'opts.order', ['ascending', 'descending']); + var stack = [0, array.length - 1]; + while (stack.length > 0) { + var end = stack.pop(); + var start = stack.pop(); + if (start >= end) { + continue; + } + var pivotIndex = __partition(array, start, end); + stack.push(start, pivotIndex - 1); + stack.push(pivotIndex + 1, end); + } + function __partition(arr, start, end) { + function __swap(arr, a, b) { + var temp = arr[a]; + arr[a] = arr[b]; + arr[b] = temp; + } + var pivotValue = arr[end]; + var partitionIndex = start; + for (var i = start; i < end; i++) { + if (comparator(arr[i], pivotValue) < 0) { + __swap(arr, i, partitionIndex); + partitionIndex++; + } + } + __swap(arr, end, partitionIndex); + return partitionIndex; + } + return array; }; diff --git a/cjs/radix-sort.js b/cjs/radix-sort.js index a08c5e1..0556a2f 100644 --- a/cjs/radix-sort.js +++ b/cjs/radix-sort.js @@ -1,69 +1,52 @@ -'use strict'; -var __spreadArray = - (this && this.__spreadArray) || - function (to, from, pack) { - if (pack || arguments.length === 2) - for (var i = 0, l = from.length, ar; i < l; i++) { - if (ar || !(i in from)) { - if (!ar) ar = Array.prototype.slice.call(from, 0, i); - ar[i] = from[i]; - } - } - return to.concat(ar || Array.prototype.slice.call(from)); - }; -var assertDefined = require('@santi100/assertion-lib/cjs/defined'); -var assertInstanceOf = require('@santi100/assertion-lib/cjs/instance-of'); -var assertOneOf = require('@santi100/assertion-lib/cjs/one-of'); -var assertTypeOf = require('@santi100/assertion-lib/cjs/type-of'); -var core_1 = require('./core'); +"use strict"; +var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +}; +var assertDefined = require("@santi100/assertion-lib/cjs/defined"); +var assertInstanceOf = require("@santi100/assertion-lib/cjs/instance-of"); +var assertOneOf = require("@santi100/assertion-lib/cjs/one-of"); +var assertTypeOf = require("@santi100/assertion-lib/cjs/type-of"); +var core_1 = require("./core"); module.exports = function radixSort(arr, opts) { - var _a; - var _b; - if (opts === void 0) { - opts = {}; - } - assertInstanceOf(arr, Array, 'arr'); - assertDefined(opts, 'opts'); - assertTypeOf(opts, 'object'); - for (var _i = 0, arr_1 = arr; _i < arr_1.length; _i++) { - var item = arr_1[_i]; - if (!(0, core_1.__isInteger)(item)) - throw new TypeError( - '"arr" must be an Array of integers. Item #' - .concat( - (_b = arr === null || arr === void 0 ? void 0 : arr.indexOf) === - null || _b === void 0 - ? void 0 - : _b.call(arr, item), - ' of "arr" is "' - ) - .concat(item, '" of type "') - .concat(typeof item, '".') - ); - } - var array = __spreadArray([], arr, true); - var _c = opts.order, - order = _c === void 0 ? 'ascending' : _c; - assertOneOf(order, 'opts.order', ['ascending', 'descending']); - var maxDigits = 0; - var getNumberOfDigits = function (n) { - return Math.floor(Math.log(n) / Math.log(10)) + 1; - }; - var getDigit = function (n, p) { - return p >= Math.floor(Math.log(Math.abs(n)) / Math.log(10)) + 1 - ? 0 - : Math.floor((Math.abs(n) / Math.pow(10, p)) % 10); - }; - for (var i = 0; i < array.length; i++) { - maxDigits = Math.max(maxDigits, getNumberOfDigits(arr[i])); - } - for (var i = 0; i < maxDigits; i++) { - var buckets = [[], [], [], [], [], [], [], [], [], []]; - for (var j = 0; j < array.length; j++) { - var digit = getDigit(arr[j], i); - buckets[digit].push(arr[j]); - } - array = (_a = []).concat.apply(_a, buckets); - } - return order === 'ascending' ? array : (0, core_1.__reverse)(array); + var _a; + var _b; + if (opts === void 0) { opts = {}; } + assertInstanceOf(arr, Array, 'arr'); + assertDefined(opts, 'opts'); + assertTypeOf(opts, 'object'); + for (var _i = 0, arr_1 = arr; _i < arr_1.length; _i++) { + var item = arr_1[_i]; + if (!(0, core_1.__isInteger)(item)) + throw new TypeError("\"arr\" must be an Array of integers. Item #".concat((_b = arr === null || arr === void 0 ? void 0 : arr.indexOf) === null || _b === void 0 ? void 0 : _b.call(arr, item), " of \"arr\" is \"").concat(item, "\" of type \"").concat(typeof item, "\".")); + } + var array = __spreadArray([], arr, true); + var _c = opts.order, order = _c === void 0 ? 'ascending' : _c; + assertOneOf(order, 'opts.order', ['ascending', 'descending']); + var maxDigits = 0; + var getNumberOfDigits = function (n) { + return Math.floor(Math.log(n) / Math.log(10)) + 1; + }; + var getDigit = function (n, p) { + return p >= Math.floor(Math.log(Math.abs(n)) / Math.log(10)) + 1 + ? 0 + : Math.floor((Math.abs(n) / Math.pow(10, p)) % 10); + }; + for (var i = 0; i < array.length; i++) { + maxDigits = Math.max(maxDigits, getNumberOfDigits(arr[i])); + } + for (var i = 0; i < maxDigits; i++) { + var buckets = [[], [], [], [], [], [], [], [], [], []]; + for (var j = 0; j < array.length; j++) { + var digit = getDigit(arr[j], i); + buckets[digit].push(arr[j]); + } + array = (_a = []).concat.apply(_a, buckets); + } + return order === 'ascending' ? array : (0, core_1.__reverse)(array); }; diff --git a/cjs/selection-sort.js b/cjs/selection-sort.js index c852eb0..14373fc 100644 --- a/cjs/selection-sort.js +++ b/cjs/selection-sort.js @@ -1,50 +1,37 @@ -'use strict'; -var __spreadArray = - (this && this.__spreadArray) || - function (to, from, pack) { - if (pack || arguments.length === 2) - for (var i = 0, l = from.length, ar; i < l; i++) { - if (ar || !(i in from)) { - if (!ar) ar = Array.prototype.slice.call(from, 0, i); - ar[i] = from[i]; - } - } - return to.concat(ar || Array.prototype.slice.call(from)); - }; -var assertDefined = require('@santi100/assertion-lib/cjs/defined'); -var assertInstanceOf = require('@santi100/assertion-lib/cjs/instance-of'); -var assertOneOf = require('@santi100/assertion-lib/cjs/one-of'); -var assertTypeOf = require('@santi100/assertion-lib/cjs/type-of'); -var core_1 = require('./core'); +"use strict"; +var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +}; +var assertDefined = require("@santi100/assertion-lib/cjs/defined"); +var assertInstanceOf = require("@santi100/assertion-lib/cjs/instance-of"); +var assertOneOf = require("@santi100/assertion-lib/cjs/one-of"); +var assertTypeOf = require("@santi100/assertion-lib/cjs/type-of"); +var core_1 = require("./core"); module.exports = function selectionSort(arr, opts) { - var _a; - if (opts === void 0) { - opts = {}; - } - assertInstanceOf(arr, Array, 'arr'); - assertDefined(opts, 'opts'); - assertTypeOf(opts, 'object'); - var array = __spreadArray([], arr, true); - var _b = opts.order, - order = _b === void 0 ? 'ascending' : _b, - _c = opts.comparator, - comparator = - _c === void 0 - ? order === 'ascending' - ? core_1.__defAscending - : core_1.__defDescending - : _c; - assertOneOf(order, 'opts.order', ['ascending', 'descending']); - for (var i = 0; i < array.length; i++) { - var min = i; - for (var j = i + 1; j < array.length; j++) { - if (comparator(array[j], array[min]) < 0) { - min = j; - } - } - if (min !== i) { - (_a = [array[min], array[i]]), (array[i] = _a[0]), (array[min] = _a[1]); - } - } - return array; + var _a; + if (opts === void 0) { opts = {}; } + assertInstanceOf(arr, Array, 'arr'); + assertDefined(opts, 'opts'); + assertTypeOf(opts, 'object'); + var array = __spreadArray([], arr, true); + var _b = opts.order, order = _b === void 0 ? 'ascending' : _b, _c = opts.comparator, comparator = _c === void 0 ? order === 'ascending' ? core_1.__defAscending : core_1.__defDescending : _c; + assertOneOf(order, 'opts.order', ['ascending', 'descending']); + for (var i = 0; i < array.length; i++) { + var min = i; + for (var j = i + 1; j < array.length; j++) { + if (comparator(array[j], array[min]) < 0) { + min = j; + } + } + if (min !== i) { + _a = [array[min], array[i]], array[i] = _a[0], array[min] = _a[1]; + } + } + return array; }; diff --git a/cjs/shell-sort.js b/cjs/shell-sort.js index dabf470..9637ef2 100644 --- a/cjs/shell-sort.js +++ b/cjs/shell-sort.js @@ -1,40 +1,30 @@ -'use strict'; -var assertDefined = require('@santi100/assertion-lib/cjs/defined'); -var assertInstanceOf = require('@santi100/assertion-lib/cjs/instance-of'); -var assertOneOf = require('@santi100/assertion-lib/cjs/one-of'); -var assertTypeOf = require('@santi100/assertion-lib/cjs/type-of'); -var core_1 = require('./core'); +"use strict"; +var assertDefined = require("@santi100/assertion-lib/cjs/defined"); +var assertInstanceOf = require("@santi100/assertion-lib/cjs/instance-of"); +var assertOneOf = require("@santi100/assertion-lib/cjs/one-of"); +var assertTypeOf = require("@santi100/assertion-lib/cjs/type-of"); +var core_1 = require("./core"); module.exports = function shellSort(arr, opts) { - if (opts === void 0) { - opts = {}; - } - assertInstanceOf(arr, Array, 'arr'); - assertDefined(opts, 'opts'); - assertTypeOf(opts, 'object'); - var array = arr.slice(); - var _a = opts.order, - order = _a === void 0 ? 'ascending' : _a, - _b = opts.comparator, - comparator = - _b === void 0 - ? order === 'ascending' - ? core_1.__defAscending - : core_1.__defDescending - : _b; - var len = array.length; - var gap = Math.floor(len / 2); - assertOneOf(order, 'opts.order', ['ascending', 'descending']); - while (gap > 0) { - for (var i = gap; i < len; i++) { - var temp = array[i]; - var j = i; - while (j >= gap && comparator(array[j - gap], temp) > 0) { - array[j] = array[j - gap]; - j -= gap; - } - array[j] = temp; - } - gap = Math.floor(gap / 2); - } - return array.slice(); + if (opts === void 0) { opts = {}; } + assertInstanceOf(arr, Array, 'arr'); + assertDefined(opts, 'opts'); + assertTypeOf(opts, 'object'); + var array = arr.slice(); + var _a = opts.order, order = _a === void 0 ? 'ascending' : _a, _b = opts.comparator, comparator = _b === void 0 ? order === 'ascending' ? core_1.__defAscending : core_1.__defDescending : _b; + var len = array.length; + var gap = Math.floor(len / 2); + assertOneOf(order, 'opts.order', ['ascending', 'descending']); + while (gap > 0) { + for (var i = gap; i < len; i++) { + var temp = array[i]; + var j = i; + while (j >= gap && comparator(array[j - gap], temp) > 0) { + array[j] = array[j - gap]; + j -= gap; + } + array[j] = temp; + } + gap = Math.floor(gap / 2); + } + return array.slice(); }; diff --git a/package.json b/package.json index eac5a52..268ef69 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@santi100/sorting-lib", - "version": "0.0.4", + "version": "0.0.5", "main": "cjs/index.js", "module": "index.mjs", "typings": "cjs/index.d.ts", @@ -49,6 +49,7 @@ }, "dependencies": { "@santi100/array-shuffle": "^0.0.2", - "@santi100/assertion-lib": "^2.0.2" + "@santi100/assertion-lib": "^2.0.2", + "@santi100/random-lib": "^1.1.7" } } diff --git a/src/bogo-sort.ts b/src/bogo-sort.ts index 3dc7ce5..8b2c343 100644 --- a/src/bogo-sort.ts +++ b/src/bogo-sort.ts @@ -3,7 +3,7 @@ import assertInstanceOf = require('@santi100/assertion-lib/cjs/instance-of'); import assertOneOf = require('@santi100/assertion-lib/cjs/one-of'); import assertTypeOf = require('@santi100/assertion-lib/cjs/type-of'); import shuffle = require('@santi100/array-shuffle'); -import { SortOptions, __defAscending, __defDescending } from './core'; +import { SortOptions, __defAscending, __defDescending, __isSorted } from './core'; /** * Sorts `arr` with bogo-sort and returns a new sorted array (i.e.: doesn't mutate `arr`). @@ -24,18 +24,9 @@ export = function bogoSort(arr: T[], opts: SortOptions = {}) { comparator = order === 'ascending' ? __defAscending : __defDescending } = opts; assertOneOf(order, 'opts.order', ['ascending', 'descending']); - function __isSorted(arr: T[]) { - const array = [...arr]; - let sorted = true; - for (let i = 0; i < array.length - 1; i++) { - if (comparator(array[i + 1], array[i]) < 0) { - sorted = false; - } - } - return sorted; - } + let array = [...arr]; - - while (!__isSorted(array)) array = shuffle(array); + + while (!__isSorted(array, comparator)) array = shuffle(array); return array; }; diff --git a/src/bozo-sort.ts b/src/bozo-sort.ts new file mode 100644 index 0000000..c6ea190 --- /dev/null +++ b/src/bozo-sort.ts @@ -0,0 +1,54 @@ +import { + SortOptions, + SortOrder, + __defAscending, + __defDescending, + __isSorted +} from './core'; +import randomIntegers = require('@santi100/random-lib/cjs/random-integers'); +import assertArray = require('@santi100/assertion-lib/cjs/array'); +import assertDefined = require('@santi100/assertion-lib/cjs/defined'); +import assertTypeOf = require('@santi100/assertion-lib/cjs/type-of'); +import assertOneOf = require('@santi100/assertion-lib/cjs/one-of'); +/** + * Sorts an array using the Bozo Sort algorithm. + * + * @template T The type of elements in the array. + * @param {T[]} array The array to be sorted. + */ +function bozoSort(array: T[]): T[]; +/** + * Sorts an array using the Bozo Sort algorithm. + * + * @template T The type of elements in the array. + * @param {T[]} array The array to be sorted. + * @param {SortOptions} [opts] An object containing sorting options. + */ +function bozoSort(array: T[], opts: SortOptions): T[]; + +function bozoSort( + array: T[], + opts: SortOptions = { + order: 'ascending', + comparator: __defAscending + } +): T[] { + const arr = [...array]; + assertArray(array, 'array'); + assertDefined(opts, 'opts'); + assertTypeOf(opts, 'object', 'opts'); + const { + order = 'ascending', + comparator = order === 'ascending' ? __defAscending : __defDescending + } = opts; + assertTypeOf(order, 'string', 'order'); + assertOneOf(order, 'order', ['ascending', 'descending'] as SortOrder[]); + assertTypeOf(comparator, 'function', 'comparator'); + while (!__isSorted(arr, comparator)) { + const [i, j] = randomIntegers(2, { max: array.length, min: 0 }); + [arr[i], arr[j]] = [arr[j], arr[i]]; // swap + } + return arr; +} + +export = bozoSort; diff --git a/src/core.ts b/src/core.ts index bdfb4c1..ff3b0f8 100644 --- a/src/core.ts +++ b/src/core.ts @@ -34,7 +34,7 @@ export interface RadixSortOptions { order?: SortOrder; } /** - * Shape of the `opts` object exclusive to {@link countingSort}. + * Shape of the `opts` object exclusive to `countingSort`. * @since 0.0.3 */ export type CountingSortOptions = RadixSortOptions; @@ -63,3 +63,14 @@ export function __isInteger(num: number) { (num < 0 ? Math.ceil(num) : Math.floor(num)) === num ); } + +export function __isSorted(arr: T[], comparator: SortComparator) { + const array = [...arr]; + let sorted = true; + for (let i = 0; i < array.length - 1; i++) { + if (comparator(array[i + 1], array[i]) < 0) { + sorted = false; + } + } + return sorted; +} diff --git a/src/index.ts b/src/index.ts index 5028bb5..aa10380 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,5 @@ import bogoSort = require('./bogo-sort'); +import bozoSort = require('./bozo-sort'); import bubbleSort = require('./bubble-sort'); import countingSort = require('./counting-sort'); import heapSort = require('./heap-sort'); @@ -11,6 +12,7 @@ import shellSort = require('./shell-sort'); export { bogoSort, + bozoSort, bubbleSort, countingSort, heapSort, @@ -19,5 +21,5 @@ export { quickSort, radixSort, selectionSort, - shellSort + shellSort, }; diff --git a/tests/bozoSort.test.js b/tests/bozoSort.test.js new file mode 100644 index 0000000..88c5d51 --- /dev/null +++ b/tests/bozoSort.test.js @@ -0,0 +1,72 @@ +describe('bozoSort', () => { + const bozoSort = require('../cjs/bozo-sort'); + const unsortedArray = [4, 1, 2, 3]; + const sortedArray = [1, 2, 3, 4]; + const reverseSortedArray = [4, 3, 2, 1]; + const objArray = [ + { name: 'John', age: 25 }, + { name: 'Jane', age: 21 }, + { name: 'Bob', age: 30 } + ]; + const sortedObjArrayByName = [ + { name: 'Bob', age: 30 }, + { name: 'Jane', age: 21 }, + { name: 'John', age: 25 } + ]; + const sortedObjArrayByAge = [ + { name: 'Jane', age: 21 }, + { name: 'John', age: 25 }, + { name: 'Bob', age: 30 } + ]; + describe('error handling', () => { + test('throws TypeError if "arr" is not an array', () => { + expect(() => { + bozoSort('not an array', {}); + }).toThrow(TypeError); + }); + + test('throws TypeError if "opts" is not an object', () => { + expect(() => { + bozoSort([], 'not an object'); + }).toThrow(TypeError); + }); + + test('throws TypeError if "opts.order" is not valid', () => { + expect(() => { + bozoSort([], { order: 'invalid' }); + }).toThrow(TypeError); + }); + }); + test('it can sort an already sorted array', () => { + expect(bozoSort(sortedArray)).toEqual(sortedArray); + expect(bozoSort(sortedArray, { order: 'descending' })).toEqual( + reverseSortedArray + ); + }); + test('it can sort an array in both orders', () => { + expect(bozoSort(unsortedArray)).toEqual(sortedArray); + expect(bozoSort(unsortedArray, { order: 'ascending' })).toEqual( + sortedArray + ); + expect(bozoSort(unsortedArray, { order: 'descending' })).toEqual( + reverseSortedArray + ); + }); + test('it can use a custom comparator', () => { + const comparator = (a, b) => a.age - b.age; + expect(bozoSort(objArray, { comparator })).toEqual(sortedObjArrayByAge); + expect( + bozoSort(objArray, { + comparator(a, b) { + if (a.name < b.name) return -1; + if (a.name > b.name) return 1; + return 0; + } + }) + ).toEqual(sortedObjArrayByName); + }); + test('code splitting', () => { + const bigModule = require('..'); + expect(bigModule.bozoSort).toBe(bozoSort); + }); +});