├── .eslintrc.json ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── jsdoc.json ├── package-lock.json ├── package.json ├── rollup.config.js ├── src ├── utils.spec.ts └── utils.ts └── tsconfig.json /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "@typescript-eslint/parser", 3 | "parserOptions": { 4 | "ecmaVersion": 2020, 5 | "sourceType": "module", 6 | "ecmaFeatures": { 7 | "jsx": true 8 | } 9 | }, 10 | "extends": [ 11 | "plugin:@typescript-eslint/recommended" 12 | ], 13 | "rules": { 14 | } 15 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_module 2 | dist -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakura90/sorted-array-operations/ca964d4402d665832baa69bce1aa6cba0f03a664/.npmignore -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 |

Sorted Array Operations

3 |

Sorted array operation module that has a broad operation coverage.

4 | 5 |

6 | 7 | 8 | 9 | Tweet 10 |



11 | 12 |


13 | 14 | ## Overview 15 | Existing libraries cover non-standard operations or cover the operations partially on sorted arrays. 16 | This library is created to provide a wide range of operations on sorted arrays found in the standard libraries 17 | of major programming languages so that developers can get almost all (if not all) standard operations on sorted arrays in a library. 18 | 19 | This library features: 20 | 21 | * Language: Supports both JavaScript and TypeScript 22 | * Module: Includes both CommonJS module and ES module 23 | 24 | ## Installation 25 | Yarn & npm 26 | 27 | ``` 28 | $ yarn add sorted-array-operations 29 | $ npm install sorted-array-operations 30 | ``` 31 | 32 | CDN 33 | 34 | ``` 35 | 36 | ``` 37 | 38 | ## Usage of all library functions 39 | ```js 40 | const ops = require('sorted-array-operations'); 41 | 42 | console.log(ops.union([2, 3, 5, 6], [2, 6, 8])); // [ 2, 3, 5, 6, 8 ] 43 | console.log(ops.intersection([2, 3, 5, 6], [2, 6, 8])); // [ 2 ] 44 | console.log(ops.difference([2, 3, 5, 6], [2, 6, 8])); // [ 3, 5 ] 45 | console.log(ops.symmetric_difference([2, 3, 5, 6], [2, 6, 8])); // [ 3, 5, 8 ] 46 | console.log(ops.merge([2, 3, 5, 6], [2, 6, 8])); // [ 2, 2, 3, 5, 6, 6, 8 ] 47 | 48 | const arr1 = [2, 5, 3]; 49 | console.log(ops.inplace_merge(arr1, 2)); // arr1 becomes [ 2, 3, 5 ] 50 | 51 | console.log(ops.includes([2, 3, 5, 6], [2, 6, 8])); // false 52 | 53 | const arr2 = [2, 3, 5, 6]; 54 | console.log(ops.insert(arr2, 2)); // arr2 becomes [ 2, 2, 3, 5, 6 ] 55 | 56 | const arr3 = [2, 3, 5, 6]; 57 | console.log(ops.remove(arr3, 2)); // Return true. arr3 becomes [ 3, 5, 6 ] 58 | console.log(ops.binary_search([2, 3, 5, 6], 2)); // Return 0 59 | console.log(ops.binary_search_ge([2, 3, 5, 6], 2)); // Return 0 60 | console.log(ops.binary_search_gt([2, 3, 5, 6], 2)); // Return 1 61 | console.log(ops.equal_range([2, 3, 5, 6], 2)); // Return [ 0, 1 ] 62 | 63 | function weight_cmp(p1, p2) { 64 | return p1.weight > p2.weight ? 1 : p1.weight < p2.weight ? -1 : 0; 65 | } 66 | 67 | console.log(ops.union([{weight: 2}, {weight: 3}], [{weight: 3}], weight_cmp)); // [ {weight: 2}, {weight: 3} ] 68 | console.log(ops.intersection([{weight: 2}, {weight: 3}], [{weight: 3}], weight_cmp)); // [ {weight: 3} ] 69 | console.log(ops.difference([{weight: 2}, {weight: 3}], [{weight: 3}], weight_cmp)); // [ {weight: 2} ] 70 | console.log(ops.symmetric_difference([{weight: 2}, {weight: 3}], [{weight: 3},{weight: 4}], weight_cmp)); // [ {weight: 2}, {weight: 4} ] 71 | console.log(ops.merge([{weight: 2}, {weight: 3}], [{weight: 3}], weight_cmp)); // [ {weight: 2}, {weight: 3}, {weight: 3} ] 72 | 73 | const arr4 = [{weight: 3}, {weight: 1}]; 74 | console.log(ops.inplace_merge(arr4, 1, weight_cmp)); // arr4 becomes [ {weight: 1}, {weight: 3} ] 75 | 76 | console.log(ops.includes([{weight: 2}, {weight: 3}], [{weight: 3}], weight_cmp)); // true 77 | 78 | const arr5 = [{weight: 3}]; 79 | console.log(ops.insert(arr5, {weight: 2}, weight_cmp)); // arr5 becomes [ {weight: 2}, {weight: 3} ] 80 | 81 | const arr6 = [{weight: 3}]; 82 | console.log(ops.remove(arr6, {weight: 3}, weight_cmp)); // Return true. arr6 becomes [ ] 83 | console.log(ops.binary_search([{weight: 2}, {weight: 3}], {weight: 2}, weight_cmp)); // Return 0 84 | console.log(ops.binary_search_ge([{weight: 2}, {weight: 3}], {weight: 2}, weight_cmp)); // Return 0 85 | console.log(ops.binary_search_gt([{weight: 2}, {weight: 3}], {weight: 2}, weight_cmp)); // Return 1 86 | console.log(ops.equal_range([{weight: 2}, {weight: 3}], {weight: 2}, weight_cmp)); // Return [ 0, 1 ] 87 | ``` 88 | 89 | ## Related libraries 90 | The library most similar to this library is [sorted-array-functions](https://www.npmjs.com/package/sorted-array-functions). 91 | This library has the set operations on sorted arrays and follows the way of implementing `lower_bound` and `upper_bound` 92 | in the standard libraries in C++ and Python. These 2 differences are the major differences between this library and 93 | [sorted-array-functions](https://www.npmjs.com/package/sorted-array-functions). 94 | Other related libraries can be found in Google search. 95 | 96 | ## Contributing 97 | The sorted array operation library welcomes patches/pulls for features and bug fixes. Please open an issue and send a PR request! 98 | -------------------------------------------------------------------------------- /jsdoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "tags": { 3 | "allowUnknownTags": true, 4 | "dictionaries": ["jsdoc", "closure"] 5 | }, 6 | "source": { 7 | "include": ["."], 8 | "includePattern": ".ts" 9 | }, 10 | "sourceType": "module" 11 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sorted-array-operations", 3 | "version": "1.0.0", 4 | "description": "Broad coverage of sorted array operations", 5 | "main": "dist/utils.common.js", 6 | "module": "dist/utils.esm.js", 7 | "types": "dist/utils.d.ts", 8 | "scripts": { 9 | "build": "rimraf dist && rollup --config", 10 | "eslint": "eslint \"src/utils.ts\"", 11 | "test": "jest", 12 | "jsdoc": "echo \"Error: jsdoc error due to TS type handling not being supported yet.\" && exit 1", 13 | "prettier": "prettier --write \"src/**/*.ts\"" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/sakura90/sorted-array-operations.git" 18 | }, 19 | "keywords": [ 20 | "sorted array", 21 | "operations", 22 | "commonjs", 23 | "ES module", 24 | "insert", 25 | "remove", 26 | "union", 27 | "intersection", 28 | "difference", 29 | "symmetric difference", 30 | "inplace merge", 31 | "includes", 32 | "binary search", 33 | "lower bound", 34 | "upper bound", 35 | "bisect left", 36 | "bisect right", 37 | "equal range", 38 | "merge" 39 | ], 40 | "author": "Patrick Chan", 41 | "license": "Apache-2.0", 42 | "bugs": { 43 | "url": "https://github.com/sakura90/sorted-array-operations/issues" 44 | }, 45 | "homepage": "https://github.com/sakura90/sorted-array-operations#readme", 46 | "devDependencies": { 47 | "@types/jest": "^26.0.20", 48 | "@types/node": "^14.14.32", 49 | "@types/source-map": "^0.5.2", 50 | "@typescript-eslint/eslint-plugin": "^4.29.1", 51 | "@typescript-eslint/parser": "^4.29.1", 52 | "babel-jest": "^27.0.6", 53 | "eslint": "^7.32.0", 54 | "jest": "^27.0.6", 55 | "jsdoc": "^3.6.7", 56 | "prettier": "^2.2.1", 57 | "rimraf": "^3.0.2", 58 | "rollup": "^2.56.2", 59 | "rollup-plugin-terser": "^7.0.2", 60 | "rollup-plugin-typescript2": "^0.30.0", 61 | "source-map": "^0.7.3", 62 | "ts-jest": "^27.0.5", 63 | "typescript": "^4.3.5" 64 | }, 65 | "jest": { 66 | "moduleFileExtensions": [ 67 | "js", 68 | "ts" 69 | ], 70 | "rootDir": "src", 71 | "testRegex": ".spec.ts$", 72 | "transform": { 73 | "^.+\\.(t|j)s$": "ts-jest" 74 | }, 75 | "coverageDirectory": "../coverage", 76 | "testEnvironment": "node" 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import typescript from "rollup-plugin-typescript2"; 2 | import { terser } from "rollup-plugin-terser"; 3 | import pkg from "./package.json"; 4 | 5 | export default { 6 | input: "src/utils.ts", 7 | output: [ 8 | { 9 | file: pkg.main, 10 | format: "cjs", 11 | sourcemap: true 12 | }, 13 | { 14 | file: pkg.module, 15 | format: "es", 16 | sourcemap: true 17 | }, 18 | ], 19 | plugins: [ 20 | typescript({ 21 | typescript: require("typescript"), 22 | tsconfig: 'tsconfig.json', 23 | }), 24 | terser(), 25 | ], 26 | }; 27 | -------------------------------------------------------------------------------- /src/utils.spec.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license Apache-2.0 3 | * 4 | * Copyright (c) 2021 Patrick Chan 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | const utils = require("./utils"); 20 | 21 | function polygon_cmp(p1, p2) { 22 | if (p1.edge === p2.edge) { 23 | return p1.name > p2.name ? 1 : p1.name < p2.name ? -1 : 0; 24 | } else if (p1.edge < p2.edge) { 25 | return -1; 26 | } 27 | return 1; 28 | } 29 | 30 | describe("intersection", () => { 31 | test("intersectionEmptyRetvalObjArrVal", () => { 32 | const triangle = { name: "triangle", edge: 3 }; 33 | const square = { name: "square", edge: 4 }; 34 | const pentagon = { name: "pentagon", edge: 5 }; 35 | const hexagon = { name: "hexagon", edge: 6 }; 36 | 37 | const testArr = utils.intersection( 38 | [triangle, pentagon], 39 | [square, hexagon], 40 | polygon_cmp 41 | ); 42 | const expectedArr = []; 43 | expect(testArr.length).toEqual(expectedArr.length); 44 | for (let i = 0; i < testArr.length; ++i) { 45 | expect(testArr[i]).toEqual(expectedArr[i]); 46 | } 47 | }); 48 | 49 | test("intersectionEmptyArrArgObjArrVal", () => { 50 | const triangle = { name: "triangle", edge: 3 }; 51 | const pentagon = { name: "pentagon", edge: 5 }; 52 | 53 | const testArr = utils.intersection([triangle, pentagon], [], polygon_cmp); 54 | const expectedArr = []; 55 | expect(testArr.length).toEqual(expectedArr.length); 56 | for (let i = 0; i < testArr.length; ++i) { 57 | expect(testArr[i]).toEqual(expectedArr[i]); 58 | } 59 | }); 60 | 61 | test("intersectionSubarrayIntersectObjArrVal", () => { 62 | const triangle1 = { name: "triangle", edge: 3 }; 63 | const triangle2 = { name: "triangle", edge: 3 }; 64 | const square = { name: "square", edge: 4 }; 65 | const pentagon = { name: "pentagon", edge: 5 }; 66 | const expectedTriangle = { name: "triangle", edge: 3 }; 67 | 68 | const testArr = utils.intersection( 69 | [triangle1, pentagon], 70 | [triangle2, square], 71 | polygon_cmp 72 | ); 73 | const expectedArr = [expectedTriangle]; 74 | expect(testArr.length).toEqual(expectedArr.length); 75 | for (let i = 0; i < testArr.length; ++i) { 76 | expect(testArr[i]).toEqual(expectedArr[i]); 77 | } 78 | }); 79 | 80 | test("intersectionSubarrayIntersectDupValObjArrVal", () => { 81 | const triangle1 = { name: "triangle", edge: 3 }; 82 | const triangle2 = { name: "triangle", edge: 3 }; 83 | const triangle3 = { name: "triangle", edge: 3 }; 84 | const triangle4 = { name: "triangle", edge: 3 }; 85 | const square = { name: "square", edge: 4 }; 86 | const pentagon = { name: "pentagon", edge: 5 }; 87 | const expectedTriangle1 = { name: "triangle", edge: 3 }; 88 | const expectedTriangle2 = { name: "triangle", edge: 3 }; 89 | 90 | const testArr = utils.intersection( 91 | [triangle1, triangle2, pentagon], 92 | [triangle3, triangle4, square], 93 | polygon_cmp 94 | ); 95 | const expectedArr = [expectedTriangle1, expectedTriangle2]; 96 | expect(testArr.length).toEqual(expectedArr.length); 97 | for (let i = 0; i < testArr.length; ++i) { 98 | expect(testArr[i]).toEqual(expectedArr[i]); 99 | } 100 | }); 101 | 102 | test("intersectionDupValObjArrVal", () => { 103 | const triangle1 = { name: "triangle", edge: 3 }; 104 | const triangle2 = { name: "triangle", edge: 3 }; 105 | const triangle3 = { name: "triangle", edge: 3 }; 106 | const expectedTriangle = { name: "triangle", edge: 3 }; 107 | 108 | const testArr = utils.intersection( 109 | [triangle1, triangle2], 110 | [triangle3], 111 | polygon_cmp 112 | ); 113 | const expectedArr = [expectedTriangle]; 114 | expect(testArr.length).toEqual(expectedArr.length); 115 | for (let i = 0; i < testArr.length; ++i) { 116 | expect(testArr[i]).toEqual(expectedArr[i]); 117 | } 118 | }); 119 | 120 | test("intersectionAllValSameObjArrVal", () => { 121 | const triangle1 = { name: "triangle", edge: 3 }; 122 | const triangle2 = { name: "triangle", edge: 3 }; 123 | const pentagon1 = { name: "pentagon", edge: 5 }; 124 | const pentagon2 = { name: "pentagon", edge: 5 }; 125 | const expectedPentagon = { name: "pentagon", edge: 5 }; 126 | const expectedTriangle = { name: "triangle", edge: 3 }; 127 | 128 | const testArr = utils.intersection( 129 | [triangle1, pentagon1], 130 | [triangle2, pentagon2], 131 | polygon_cmp 132 | ); 133 | const expectedArr = [expectedTriangle, expectedPentagon]; 134 | expect(testArr.length).toEqual(expectedArr.length); 135 | for (let i = 0; i < testArr.length; ++i) { 136 | expect(testArr[i]).toEqual(expectedArr[i]); 137 | } 138 | }); 139 | 140 | test("intersectionEmptyRetval", () => { 141 | const testArr = utils.intersection([1, 3], [2, 4]); 142 | const expectedArr = []; 143 | expect(testArr.length).toEqual(expectedArr.length); 144 | for (let i = 0; i < testArr.length; ++i) { 145 | expect(testArr[i]).toEqual(expectedArr[i]); 146 | } 147 | }); 148 | 149 | test("intersectionEmptyArrArg", () => { 150 | const testArr = utils.intersection([1, 3], []); 151 | const expectedArr = []; 152 | expect(testArr.length).toEqual(expectedArr.length); 153 | for (let i = 0; i < testArr.length; ++i) { 154 | expect(testArr[i]).toEqual(expectedArr[i]); 155 | } 156 | }); 157 | 158 | test("intersectionSubarrayIntersect", () => { 159 | const testArr = utils.intersection([1, 3], [1, 2]); 160 | const expectedArr = [1]; 161 | expect(testArr.length).toEqual(expectedArr.length); 162 | for (let i = 0; i < testArr.length; ++i) { 163 | expect(testArr[i]).toEqual(expectedArr[i]); 164 | } 165 | }); 166 | 167 | test("intersectionSubarrayIntersectDupVal", () => { 168 | const testArr = utils.intersection([1, 1, 3], [1, 1, 2]); 169 | const expectedArr = [1, 1]; 170 | expect(testArr.length).toEqual(expectedArr.length); 171 | for (let i = 0; i < testArr.length; ++i) { 172 | expect(testArr[i]).toEqual(expectedArr[i]); 173 | } 174 | }); 175 | 176 | test("intersectionDupVal", () => { 177 | const testArr = utils.intersection([1, 1], [1]); 178 | const expectedArr = [1]; 179 | expect(testArr.length).toEqual(expectedArr.length); 180 | for (let i = 0; i < testArr.length; ++i) { 181 | expect(testArr[i]).toEqual(expectedArr[i]); 182 | } 183 | }); 184 | 185 | test("intersectionAllValSame", () => { 186 | const testArr = utils.intersection([1, 3], [1, 3]); 187 | const expectedArr = [1, 3]; 188 | expect(testArr.length).toEqual(expectedArr.length); 189 | for (let i = 0; i < testArr.length; ++i) { 190 | expect(testArr[i]).toEqual(expectedArr[i]); 191 | } 192 | }); 193 | }); 194 | 195 | describe("union", () => { 196 | test("unionEmptyRetvalObjArrVal", () => { 197 | const testArr = utils.union([], [], polygon_cmp); 198 | const expectedArr = []; 199 | expect(testArr.length).toEqual(expectedArr.length); 200 | for (let i = 0; i < testArr.length; ++i) { 201 | expect(testArr[i]).toEqual(expectedArr[i]); 202 | } 203 | }); 204 | 205 | test("unionNoIntersectedValObjArrVal", () => { 206 | const triangle = { name: "triangle", edge: 3 }; 207 | const square = { name: "square", edge: 4 }; 208 | const pentagon = { name: "pentagon", edge: 5 }; 209 | const hexagon = { name: "hexagon", edge: 6 }; 210 | const expectedTriangle = { name: "triangle", edge: 3 }; 211 | const expectedSquare = { name: "square", edge: 4 }; 212 | const expectedPentagon = { name: "pentagon", edge: 5 }; 213 | const expectedHexagon = { name: "hexagon", edge: 6 }; 214 | 215 | const testArr = utils.union( 216 | [triangle, pentagon], 217 | [square, hexagon], 218 | polygon_cmp 219 | ); 220 | const expectedArr = [ 221 | expectedTriangle, 222 | expectedSquare, 223 | expectedPentagon, 224 | expectedHexagon, 225 | ]; 226 | expect(testArr.length).toEqual(expectedArr.length); 227 | for (let i = 0; i < testArr.length; ++i) { 228 | expect(testArr[i]).toEqual(expectedArr[i]); 229 | } 230 | }); 231 | 232 | test("unionEmptyArrArgObjArrVal", () => { 233 | const triangle = { name: "triangle", edge: 3 }; 234 | const pentagon = { name: "pentagon", edge: 5 }; 235 | const expectedTriangle = { name: "triangle", edge: 3 }; 236 | const expectedPentagon = { name: "pentagon", edge: 5 }; 237 | 238 | const testArr = utils.union([triangle, pentagon], [], polygon_cmp); 239 | const expectedArr = [expectedTriangle, expectedPentagon]; 240 | expect(testArr.length).toEqual(expectedArr.length); 241 | for (let i = 0; i < testArr.length; ++i) { 242 | expect(testArr[i]).toEqual(expectedArr[i]); 243 | } 244 | }); 245 | 246 | test("union2DiffArrObjArrVal", () => { 247 | const triangle1 = { name: "triangle", edge: 3 }; 248 | const triangle2 = { name: "triangle", edge: 3 }; 249 | const square = { name: "square", edge: 4 }; 250 | const pentagon = { name: "pentagon", edge: 5 }; 251 | const expectedTriangle = { name: "triangle", edge: 3 }; 252 | const expectedSquare = { name: "square", edge: 4 }; 253 | const expectedPentagon = { name: "pentagon", edge: 5 }; 254 | 255 | const testArr = utils.union( 256 | [triangle1, pentagon], 257 | [triangle2, square], 258 | polygon_cmp 259 | ); 260 | const expectedArr = [expectedTriangle, expectedSquare, expectedPentagon]; 261 | expect(testArr.length).toEqual(expectedArr.length); 262 | for (let i = 0; i < testArr.length; ++i) { 263 | expect(testArr[i]).toEqual(expectedArr[i]); 264 | } 265 | }); 266 | 267 | test("union2DiffArrDupValObjArrVal", () => { 268 | const triangle1 = { name: "triangle", edge: 3 }; 269 | const triangle2 = { name: "triangle", edge: 3 }; 270 | const triangle3 = { name: "triangle", edge: 3 }; 271 | const triangle4 = { name: "triangle", edge: 3 }; 272 | const square = { name: "square", edge: 4 }; 273 | const pentagon = { name: "pentagon", edge: 5 }; 274 | const expectedTriangle1 = { name: "triangle", edge: 3 }; 275 | const expectedTriangle2 = { name: "triangle", edge: 3 }; 276 | const expectedSquare = { name: "square", edge: 4 }; 277 | const expectedPentagon = { name: "pentagon", edge: 5 }; 278 | 279 | const testArr = utils.union( 280 | [triangle1, triangle2, pentagon], 281 | [triangle3, triangle4, square], 282 | polygon_cmp 283 | ); 284 | const expectedArr = [ 285 | expectedTriangle1, 286 | expectedTriangle2, 287 | expectedSquare, 288 | expectedPentagon, 289 | ]; 290 | expect(testArr.length).toEqual(expectedArr.length); 291 | for (let i = 0; i < testArr.length; ++i) { 292 | expect(testArr[i]).toEqual(expectedArr[i]); 293 | } 294 | }); 295 | 296 | test("union2DiffArr1ValDiffInNumOfValObjArrVal", () => { 297 | const triangle1 = { name: "triangle", edge: 3 }; 298 | const triangle2 = { name: "triangle", edge: 3 }; 299 | const triangle3 = { name: "triangle", edge: 3 }; 300 | const expectedTriangle1 = { name: "triangle", edge: 3 }; 301 | const expectedTriangle2 = { name: "triangle", edge: 3 }; 302 | 303 | const testArr = utils.union( 304 | [triangle1, triangle2], 305 | [triangle3], 306 | polygon_cmp 307 | ); 308 | const expectedArr = [expectedTriangle1, expectedTriangle2]; 309 | expect(testArr.length).toEqual(expectedArr.length); 310 | for (let i = 0; i < testArr.length; ++i) { 311 | expect(testArr[i]).toEqual(expectedArr[i]); 312 | } 313 | }); 314 | 315 | test("union2SameArrObjArrVal", () => { 316 | const triangle1 = { name: "triangle", edge: 3 }; 317 | const triangle2 = { name: "triangle", edge: 3 }; 318 | const pentagon1 = { name: "pentagon", edge: 5 }; 319 | const pentagon2 = { name: "pentagon", edge: 5 }; 320 | const expectedTriangle = { name: "triangle", edge: 3 }; 321 | const expectedPentagon = { name: "pentagon", edge: 5 }; 322 | 323 | const testArr = utils.union( 324 | [triangle1, pentagon1], 325 | [triangle2, pentagon2], 326 | polygon_cmp 327 | ); 328 | const expectedArr = [expectedTriangle, expectedPentagon]; 329 | expect(testArr.length).toEqual(expectedArr.length); 330 | for (let i = 0; i < testArr.length; ++i) { 331 | expect(testArr[i]).toEqual(expectedArr[i]); 332 | } 333 | }); 334 | 335 | test("unionEmptyRetval", () => { 336 | const testArr = utils.union([], []); 337 | const expectedArr = []; 338 | expect(testArr.length).toEqual(expectedArr.length); 339 | for (let i = 0; i < testArr.length; ++i) { 340 | expect(testArr[i]).toEqual(expectedArr[i]); 341 | } 342 | }); 343 | 344 | test("unionNoIntersectedVal", () => { 345 | const testArr = utils.union([1, 3], [2, 4]); 346 | const expectedArr = [1, 2, 3, 4]; 347 | expect(testArr.length).toEqual(expectedArr.length); 348 | for (let i = 0; i < testArr.length; ++i) { 349 | expect(testArr[i]).toEqual(expectedArr[i]); 350 | } 351 | }); 352 | 353 | test("unionEmptyArrArg", () => { 354 | const testArr = utils.union([1, 3], []); 355 | const expectedArr = [1, 3]; 356 | expect(testArr.length).toEqual(expectedArr.length); 357 | for (let i = 0; i < testArr.length; ++i) { 358 | expect(testArr[i]).toEqual(expectedArr[i]); 359 | } 360 | }); 361 | 362 | test("union2DiffArr", () => { 363 | const testArr = utils.union([1, 3], [1, 2]); 364 | const expectedArr = [1, 2, 3]; 365 | expect(testArr.length).toEqual(expectedArr.length); 366 | for (let i = 0; i < testArr.length; ++i) { 367 | expect(testArr[i]).toEqual(expectedArr[i]); 368 | } 369 | }); 370 | 371 | test("union2DiffArrDupVal", () => { 372 | const testArr = utils.union([1, 1, 3], [1, 1, 2]); 373 | const expectedArr = [1, 1, 2, 3]; 374 | expect(testArr.length).toEqual(expectedArr.length); 375 | for (let i = 0; i < testArr.length; ++i) { 376 | expect(testArr[i]).toEqual(expectedArr[i]); 377 | } 378 | }); 379 | 380 | test("union2DiffArr1ValDiffInNumOfVal", () => { 381 | const testArr = utils.union([1, 1], [1]); 382 | const expectedArr = [1, 1]; 383 | expect(testArr.length).toEqual(expectedArr.length); 384 | for (let i = 0; i < testArr.length; ++i) { 385 | expect(testArr[i]).toEqual(expectedArr[i]); 386 | } 387 | }); 388 | 389 | test("union2SameArr", () => { 390 | const testArr = utils.union([1, 3], [1, 3]); 391 | const expectedArr = [1, 3]; 392 | expect(testArr.length).toEqual(expectedArr.length); 393 | for (let i = 0; i < testArr.length; ++i) { 394 | expect(testArr[i]).toEqual(expectedArr[i]); 395 | } 396 | }); 397 | }); 398 | 399 | describe("difference", () => { 400 | test("difference2ArrNoIntersectObjArrVal", () => { 401 | const triangle = { name: "triangle", edge: 3 }; 402 | const square = { name: "square", edge: 4 }; 403 | const pentagon = { name: "pentagon", edge: 5 }; 404 | const hexagon = { name: "hexagon", edge: 6 }; 405 | const expectedTriangle = { name: "triangle", edge: 3 }; 406 | const expectedPentagon = { name: "pentagon", edge: 5 }; 407 | 408 | const testArr = utils.difference( 409 | [triangle, pentagon], 410 | [square, hexagon], 411 | polygon_cmp 412 | ); 413 | const expectedArr = [expectedTriangle, expectedPentagon]; 414 | expect(testArr.length).toEqual(expectedArr.length); 415 | for (let i = 0; i < testArr.length; ++i) { 416 | expect(testArr[i]).toEqual(expectedArr[i]); 417 | } 418 | }); 419 | 420 | test("difference2ndArrEmptyObjArrVal", () => { 421 | const triangle = { name: "triangle", edge: 3 }; 422 | const pentagon = { name: "pentagon", edge: 5 }; 423 | const expectedTriangle = { name: "triangle", edge: 3 }; 424 | const expectedPentagon = { name: "pentagon", edge: 5 }; 425 | 426 | const testArr = utils.difference([triangle, pentagon], [], polygon_cmp); 427 | const expectedArr = [expectedTriangle, expectedPentagon]; 428 | expect(testArr.length).toEqual(expectedArr.length); 429 | for (let i = 0; i < testArr.length; ++i) { 430 | expect(testArr[i]).toEqual(expectedArr[i]); 431 | } 432 | }); 433 | 434 | test("difference1stArrEmptyObjArrVal", () => { 435 | const square = { name: "square", edge: 4 }; 436 | const hexagon = { name: "hexagon", edge: 6 }; 437 | 438 | const testArr = utils.difference([], [square, hexagon], polygon_cmp); 439 | const expectedArr = []; 440 | expect(testArr.length).toEqual(expectedArr.length); 441 | for (let i = 0; i < testArr.length; ++i) { 442 | expect(testArr[i]).toEqual(expectedArr[i]); 443 | } 444 | }); 445 | 446 | test("differenceOneElemIntersectObjArrVal", () => { 447 | const triangle1 = { name: "triangle", edge: 3 }; 448 | const triangle2 = { name: "triangle", edge: 3 }; 449 | const square = { name: "square", edge: 4 }; 450 | const pentagon = { name: "pentagon", edge: 5 }; 451 | const expectedPentagon = { name: "pentagon", edge: 5 }; 452 | 453 | const testArr = utils.difference( 454 | [triangle1, pentagon], 455 | [triangle2, square], 456 | polygon_cmp 457 | ); 458 | const expectedArr = [expectedPentagon]; 459 | expect(testArr.length).toEqual(expectedArr.length); 460 | for (let i = 0; i < testArr.length; ++i) { 461 | expect(testArr[i]).toEqual(expectedArr[i]); 462 | } 463 | }); 464 | 465 | test("differenceDupValIntersectObjArrVal", () => { 466 | const triangle1 = { name: "triangle", edge: 3 }; 467 | const triangle2 = { name: "triangle", edge: 3 }; 468 | const triangle3 = { name: "triangle", edge: 3 }; 469 | const triangle4 = { name: "triangle", edge: 3 }; 470 | const square = { name: "square", edge: 4 }; 471 | const pentagon = { name: "pentagon", edge: 5 }; 472 | const expectedPentagon = { name: "pentagon", edge: 5 }; 473 | 474 | const testArr = utils.difference( 475 | [triangle1, triangle2, pentagon], 476 | [triangle3, triangle4, square], 477 | polygon_cmp 478 | ); 479 | const expectedArr = [expectedPentagon]; 480 | expect(testArr.length).toEqual(expectedArr.length); 481 | for (let i = 0; i < testArr.length; ++i) { 482 | expect(testArr[i]).toEqual(expectedArr[i]); 483 | } 484 | }); 485 | 486 | test("differenceOneDupValIntersectObjArrVal", () => { 487 | const triangle1 = { name: "triangle", edge: 3 }; 488 | const triangle2 = { name: "triangle", edge: 3 }; 489 | const triangle3 = { name: "triangle", edge: 3 }; 490 | const expectedTriangle = { name: "triangle", edge: 3 }; 491 | 492 | const testArr = utils.difference( 493 | [triangle1, triangle2], 494 | [triangle3], 495 | polygon_cmp 496 | ); 497 | const expectedArr = [expectedTriangle]; 498 | expect(testArr.length).toEqual(expectedArr.length); 499 | for (let i = 0; i < testArr.length; ++i) { 500 | expect(testArr[i]).toEqual(expectedArr[i]); 501 | } 502 | }); 503 | 504 | test("differenceDupValIntersectEmptyArrObjArrVal", () => { 505 | const triangle1 = { name: "triangle", edge: 3 }; 506 | const triangle2 = { name: "triangle", edge: 3 }; 507 | const triangle3 = { name: "triangle", edge: 3 }; 508 | 509 | const testArr = utils.difference( 510 | [triangle1], 511 | [triangle2, triangle3], 512 | polygon_cmp 513 | ); 514 | const expectedArr = []; 515 | expect(testArr.length).toEqual(expectedArr.length); 516 | for (let i = 0; i < testArr.length; ++i) { 517 | expect(testArr[i]).toEqual(expectedArr[i]); 518 | } 519 | }); 520 | 521 | test("differenceSameArrObjArrVal", () => { 522 | const triangle1 = { name: "triangle", edge: 3 }; 523 | const triangle2 = { name: "triangle", edge: 3 }; 524 | const pentagon1 = { name: "pentagon", edge: 5 }; 525 | const pentagon2 = { name: "pentagon", edge: 5 }; 526 | 527 | const testArr = utils.difference( 528 | [triangle1, pentagon1], 529 | [triangle2, pentagon2], 530 | polygon_cmp 531 | ); 532 | const expectedArr = []; 533 | expect(testArr.length).toEqual(expectedArr.length); 534 | for (let i = 0; i < testArr.length; ++i) { 535 | expect(testArr[i]).toEqual(expectedArr[i]); 536 | } 537 | }); 538 | 539 | test("difference2ArrNoIntersect", () => { 540 | const testArr = utils.difference([1, 3], [2, 4]); 541 | const expectedArr = [1, 3]; 542 | expect(testArr.length).toEqual(expectedArr.length); 543 | for (let i = 0; i < testArr.length; ++i) { 544 | expect(testArr[i]).toEqual(expectedArr[i]); 545 | } 546 | }); 547 | 548 | test("difference2ndArrEmpty", () => { 549 | const testArr = utils.difference([1, 3], []); 550 | const expectedArr = [1, 3]; 551 | expect(testArr.length).toEqual(expectedArr.length); 552 | for (let i = 0; i < testArr.length; ++i) { 553 | expect(testArr[i]).toEqual(expectedArr[i]); 554 | } 555 | }); 556 | 557 | test("difference1stArrEmpty", () => { 558 | const testArr = utils.difference([], [2, 4]); 559 | const expectedArr = []; 560 | expect(testArr.length).toEqual(expectedArr.length); 561 | for (let i = 0; i < testArr.length; ++i) { 562 | expect(testArr[i]).toEqual(expectedArr[i]); 563 | } 564 | }); 565 | 566 | test("differenceOneElemIntersect", () => { 567 | const testArr = utils.difference([1, 3], [1, 2]); 568 | const expectedArr = [3]; 569 | expect(testArr.length).toEqual(expectedArr.length); 570 | for (let i = 0; i < testArr.length; ++i) { 571 | expect(testArr[i]).toEqual(expectedArr[i]); 572 | } 573 | }); 574 | 575 | test("differenceDupValIntersect", () => { 576 | const testArr = utils.difference([1, 1, 3], [1, 1, 2]); 577 | const expectedArr = [3]; 578 | expect(testArr.length).toEqual(expectedArr.length); 579 | for (let i = 0; i < testArr.length; ++i) { 580 | expect(testArr[i]).toEqual(expectedArr[i]); 581 | } 582 | }); 583 | 584 | test("differenceOneDupValIntersect", () => { 585 | const testArr = utils.difference([1, 1], [1]); 586 | const expectedArr = [1]; 587 | expect(testArr.length).toEqual(expectedArr.length); 588 | for (let i = 0; i < testArr.length; ++i) { 589 | expect(testArr[i]).toEqual(expectedArr[i]); 590 | } 591 | }); 592 | 593 | test("differenceDupValIntersectEmptyArr", () => { 594 | const testArr = utils.difference([1], [1, 1]); 595 | const expectedArr = []; 596 | expect(testArr.length).toEqual(expectedArr.length); 597 | for (let i = 0; i < testArr.length; ++i) { 598 | expect(testArr[i]).toEqual(expectedArr[i]); 599 | } 600 | }); 601 | 602 | test("differenceSameArr", () => { 603 | const testArr = utils.difference([1, 3], [1, 3]); 604 | const expectedArr = []; 605 | expect(testArr.length).toEqual(expectedArr.length); 606 | for (let i = 0; i < testArr.length; ++i) { 607 | expect(testArr[i]).toEqual(expectedArr[i]); 608 | } 609 | }); 610 | }); 611 | 612 | describe("symmetric_difference", () => { 613 | test("symmetric_differenceElemNoIntersectObjArrVal", () => { 614 | const triangle = { name: "triangle", edge: 3 }; 615 | const square = { name: "square", edge: 4 }; 616 | const pentagon = { name: "pentagon", edge: 5 }; 617 | const hexagon = { name: "hexagon", edge: 6 }; 618 | const expectedTriangle = { name: "triangle", edge: 3 }; 619 | const expectedSquare = { name: "square", edge: 4 }; 620 | const expectedPentagon = { name: "pentagon", edge: 5 }; 621 | const expectedHexagon = { name: "hexagon", edge: 6 }; 622 | 623 | const testArr = utils.symmetric_difference( 624 | [triangle, pentagon], 625 | [square, hexagon], 626 | polygon_cmp 627 | ); 628 | const expectedArr = [ 629 | expectedTriangle, 630 | expectedSquare, 631 | expectedPentagon, 632 | expectedHexagon, 633 | ]; 634 | expect(testArr.length).toEqual(expectedArr.length); 635 | for (let i = 0; i < testArr.length; ++i) { 636 | expect(testArr[i]).toEqual(expectedArr[i]); 637 | } 638 | }); 639 | 640 | test("symmetric_differenceOneElemIntersectObjArrVal", () => { 641 | const triangle = { name: "triangle", edge: 3 }; 642 | const pentagon1 = { name: "pentagon", edge: 5 }; 643 | const pentagon2 = { name: "pentagon", edge: 5 }; 644 | const hexagon = { name: "hexagon", edge: 6 }; 645 | const expectedTriangle = { name: "triangle", edge: 3 }; 646 | const expectedHexagon = { name: "hexagon", edge: 6 }; 647 | 648 | const testArr = utils.symmetric_difference( 649 | [triangle, pentagon1], 650 | [pentagon2, hexagon], 651 | polygon_cmp 652 | ); 653 | const expectedArr = [expectedTriangle, expectedHexagon]; 654 | expect(testArr.length).toEqual(expectedArr.length); 655 | for (let i = 0; i < testArr.length; ++i) { 656 | expect(testArr[i]).toEqual(expectedArr[i]); 657 | } 658 | }); 659 | 660 | test("symmetric_differenceAll2ndArrElemIn1stArrObjArrVal", () => { 661 | const triangle1 = { name: "triangle", edge: 3 }; 662 | const triangle2 = { name: "triangle", edge: 3 }; 663 | const pentagon1 = { name: "pentagon", edge: 5 }; 664 | const pentagon2 = { name: "pentagon", edge: 5 }; 665 | const expectedTriangle1 = { name: "triangle", edge: 3 }; 666 | const expectedTriangle2 = { name: "triangle", edge: 3 }; 667 | 668 | const testArr = utils.symmetric_difference( 669 | [triangle1, triangle2, pentagon1], 670 | [pentagon2], 671 | polygon_cmp 672 | ); 673 | const expectedArr = [expectedTriangle1, expectedTriangle2]; 674 | expect(testArr.length).toEqual(expectedArr.length); 675 | for (let i = 0; i < testArr.length; ++i) { 676 | expect(testArr[i]).toEqual(expectedArr[i]); 677 | } 678 | }); 679 | 680 | test("symmetric_differenceAll1stArrElemIn2ndArrObjArrVal", () => { 681 | const square = { name: "square", edge: 4 }; 682 | const pentagon1 = { name: "pentagon", edge: 5 }; 683 | const pentagon2 = { name: "pentagon", edge: 5 }; 684 | const expectedSquare = { name: "square", edge: 4 }; 685 | 686 | const testArr = utils.symmetric_difference( 687 | [pentagon1], 688 | [square, pentagon2], 689 | polygon_cmp 690 | ); 691 | const expectedArr = [expectedSquare]; 692 | expect(testArr.length).toEqual(expectedArr.length); 693 | for (let i = 0; i < testArr.length; ++i) { 694 | expect(testArr[i]).toEqual(expectedArr[i]); 695 | } 696 | }); 697 | 698 | test("symmetric_differenceSameArrObjArrVal", () => { 699 | const square1 = { name: "square", edge: 4 }; 700 | const pentagon1 = { name: "pentagon", edge: 5 }; 701 | const square2 = { name: "square", edge: 4 }; 702 | const pentagon2 = { name: "pentagon", edge: 5 }; 703 | 704 | const testArr = utils.symmetric_difference( 705 | [square1, pentagon1], 706 | [square2, pentagon2], 707 | polygon_cmp 708 | ); 709 | const expectedArr = []; 710 | expect(testArr.length).toEqual(expectedArr.length); 711 | for (let i = 0; i < testArr.length; ++i) { 712 | expect(testArr[i]).toEqual(expectedArr[i]); 713 | } 714 | }); 715 | 716 | test("symmetric_differenceEmpty1stArrObjArrVal", () => { 717 | const square = { name: "square", edge: 4 }; 718 | const pentagon = { name: "pentagon", edge: 5 }; 719 | const expectedSquare = { name: "square", edge: 4 }; 720 | const expectedPentagon = { name: "pentagon", edge: 5 }; 721 | 722 | const testArr = utils.symmetric_difference( 723 | [], 724 | [square, pentagon], 725 | polygon_cmp 726 | ); 727 | const expectedArr = [expectedSquare, expectedPentagon]; 728 | expect(testArr.length).toEqual(expectedArr.length); 729 | for (let i = 0; i < testArr.length; ++i) { 730 | expect(testArr[i]).toEqual(expectedArr[i]); 731 | } 732 | }); 733 | 734 | test("symmetric_differenceEmpty2ndArrObjArrVal", () => { 735 | const square = { name: "square", edge: 4 }; 736 | const pentagon = { name: "pentagon", edge: 5 }; 737 | const expectedSquare = { name: "square", edge: 4 }; 738 | const expectedPentagon = { name: "pentagon", edge: 5 }; 739 | 740 | const testArr = utils.symmetric_difference( 741 | [square, pentagon], 742 | [], 743 | polygon_cmp 744 | ); 745 | const expectedArr = [expectedSquare, expectedPentagon]; 746 | expect(testArr.length).toEqual(expectedArr.length); 747 | for (let i = 0; i < testArr.length; ++i) { 748 | expect(testArr[i]).toEqual(expectedArr[i]); 749 | } 750 | }); 751 | 752 | test("symmetric_differenceEmpty1stAnd2ndArrObjArrVal", () => { 753 | const testArr = utils.symmetric_difference([], [], polygon_cmp); 754 | const expectedArr = []; 755 | expect(testArr.length).toEqual(expectedArr.length); 756 | for (let i = 0; i < testArr.length; ++i) { 757 | expect(testArr[i]).toEqual(expectedArr[i]); 758 | } 759 | }); 760 | 761 | test("symmetric_differenceDupValAll2ndArrElemIn1stArrObjArrVal", () => { 762 | const square1 = { name: "square", edge: 4 }; 763 | const square2 = { name: "square", edge: 4 }; 764 | const square3 = { name: "square", edge: 4 }; 765 | const square4 = { name: "square", edge: 4 }; 766 | const square5 = { name: "square", edge: 4 }; 767 | const expectedSquare = { name: "square", edge: 4 }; 768 | 769 | const testArr = utils.symmetric_difference( 770 | [square1, square2, square3], 771 | [square4, square5], 772 | polygon_cmp 773 | ); 774 | const expectedArr = [expectedSquare]; 775 | expect(testArr.length).toEqual(expectedArr.length); 776 | for (let i = 0; i < testArr.length; ++i) { 777 | expect(testArr[i]).toEqual(expectedArr[i]); 778 | } 779 | }); 780 | 781 | test("symmetric_differenceDupValAll1stArrElemIn2ndArrObjArrVal", () => { 782 | const square1 = { name: "square", edge: 4 }; 783 | const square2 = { name: "square", edge: 4 }; 784 | const square3 = { name: "square", edge: 4 }; 785 | const square4 = { name: "square", edge: 4 }; 786 | const square5 = { name: "square", edge: 4 }; 787 | const square6 = { name: "square", edge: 4 }; 788 | const square7 = { name: "square", edge: 4 }; 789 | const square8 = { name: "square", edge: 4 }; 790 | const expectedSquare1 = { name: "square", edge: 4 }; 791 | const expectedSquare2 = { name: "square", edge: 4 }; 792 | 793 | const testArr = utils.symmetric_difference( 794 | [square1, square2, square3], 795 | [square4, square5, square6, square7, square8], 796 | polygon_cmp 797 | ); 798 | const expectedArr = [expectedSquare1, expectedSquare2]; 799 | expect(testArr.length).toEqual(expectedArr.length); 800 | for (let i = 0; i < testArr.length; ++i) { 801 | expect(testArr[i]).toEqual(expectedArr[i]); 802 | } 803 | }); 804 | 805 | test("symmetric_differenceElemNoIntersect", () => { 806 | const testArr = utils.symmetric_difference([1, 3], [2, 4]); 807 | const expectedArr = [1, 2, 3, 4]; 808 | expect(testArr.length).toEqual(expectedArr.length); 809 | for (let i = 0; i < testArr.length; ++i) { 810 | expect(testArr[i]).toEqual(expectedArr[i]); 811 | } 812 | }); 813 | 814 | test("symmetric_differenceOneElemIntersect", () => { 815 | const testArr = utils.symmetric_difference([1, 3], [3, 4]); 816 | const expectedArr = [1, 4]; 817 | expect(testArr.length).toEqual(expectedArr.length); 818 | for (let i = 0; i < testArr.length; ++i) { 819 | expect(testArr[i]).toEqual(expectedArr[i]); 820 | } 821 | }); 822 | 823 | test("symmetric_differenceAll2ndArrElemIn1stArr", () => { 824 | const testArr = utils.symmetric_difference([1, 1, 3], [3]); 825 | const expectedArr = [1, 1]; 826 | expect(testArr.length).toEqual(expectedArr.length); 827 | for (let i = 0; i < testArr.length; ++i) { 828 | expect(testArr[i]).toEqual(expectedArr[i]); 829 | } 830 | }); 831 | 832 | test("symmetric_differenceAll1stArrElemIn2ndArr", () => { 833 | const testArr = utils.symmetric_difference([3], [2, 3]); 834 | const expectedArr = [2]; 835 | expect(testArr.length).toEqual(expectedArr.length); 836 | for (let i = 0; i < testArr.length; ++i) { 837 | expect(testArr[i]).toEqual(expectedArr[i]); 838 | } 839 | }); 840 | 841 | test("symmetric_differenceSameArr", () => { 842 | const testArr = utils.symmetric_difference([2, 3], [2, 3]); 843 | const expectedArr = []; 844 | expect(testArr.length).toEqual(expectedArr.length); 845 | for (let i = 0; i < testArr.length; ++i) { 846 | expect(testArr[i]).toEqual(expectedArr[i]); 847 | } 848 | }); 849 | 850 | test("symmetric_differenceEmpty1stArr", () => { 851 | const testArr = utils.symmetric_difference([], [2, 3]); 852 | const expectedArr = [2, 3]; 853 | expect(testArr.length).toEqual(expectedArr.length); 854 | for (let i = 0; i < testArr.length; ++i) { 855 | expect(testArr[i]).toEqual(expectedArr[i]); 856 | } 857 | }); 858 | 859 | test("symmetric_differenceEmpty2ndArr", () => { 860 | const testArr = utils.symmetric_difference([2, 3], []); 861 | const expectedArr = [2, 3]; 862 | expect(testArr.length).toEqual(expectedArr.length); 863 | for (let i = 0; i < testArr.length; ++i) { 864 | expect(testArr[i]).toEqual(expectedArr[i]); 865 | } 866 | }); 867 | 868 | test("symmetric_differenceEmpty1stAnd2ndArr", () => { 869 | const testArr = utils.symmetric_difference([], []); 870 | const expectedArr = []; 871 | expect(testArr.length).toEqual(expectedArr.length); 872 | for (let i = 0; i < testArr.length; ++i) { 873 | expect(testArr[i]).toEqual(expectedArr[i]); 874 | } 875 | }); 876 | 877 | test("symmetric_differenceDupValAll2ndArrElemIn1stArr", () => { 878 | const testArr = utils.symmetric_difference([2, 2, 2], [2, 2]); 879 | const expectedArr = [2]; 880 | expect(testArr.length).toEqual(expectedArr.length); 881 | for (let i = 0; i < testArr.length; ++i) { 882 | expect(testArr[i]).toEqual(expectedArr[i]); 883 | } 884 | }); 885 | 886 | test("symmetric_differenceDupValAll1stArrElemIn2ndArr", () => { 887 | const testArr = utils.symmetric_difference([2, 2, 2], [2, 2, 2, 2, 2]); 888 | const expectedArr = [2, 2]; 889 | expect(testArr.length).toEqual(expectedArr.length); 890 | for (let i = 0; i < testArr.length; ++i) { 891 | expect(testArr[i]).toEqual(expectedArr[i]); 892 | } 893 | }); 894 | }); 895 | 896 | describe("merge", () => { 897 | test("mergeNonEmptyArrNoDupValObjArrVal", () => { 898 | const triangle = { name: "triangle", edge: 3 }; 899 | const square = { name: "square", edge: 4 }; 900 | const pentagon = { name: "pentagon", edge: 5 }; 901 | const hexagon = { name: "hexagon", edge: 6 }; 902 | const expectedTriangle = { name: "triangle", edge: 3 }; 903 | const expectedSquare = { name: "square", edge: 4 }; 904 | const expectedPentagon = { name: "pentagon", edge: 5 }; 905 | const expectedHexagon = { name: "hexagon", edge: 6 }; 906 | 907 | const testArr = utils.merge( 908 | [triangle, pentagon], 909 | [square, hexagon], 910 | polygon_cmp 911 | ); 912 | const expectedArr = [ 913 | expectedTriangle, 914 | expectedSquare, 915 | expectedPentagon, 916 | expectedHexagon, 917 | ]; 918 | expect(testArr.length).toEqual(expectedArr.length); 919 | for (let i = 0; i < testArr.length; ++i) { 920 | expect(testArr[i]).toEqual(expectedArr[i]); 921 | } 922 | }); 923 | 924 | test("mergeDupValIn1stArrObjArrVal", () => { 925 | const triangle = { name: "triangle", edge: 3 }; 926 | const square = { name: "square", edge: 4 }; 927 | const pentagon1 = { name: "pentagon", edge: 5 }; 928 | const pentagon2 = { name: "pentagon", edge: 5 }; 929 | const hexagon = { name: "hexagon", edge: 6 }; 930 | const expectedTriangle = { name: "triangle", edge: 3 }; 931 | const expectedSquare = { name: "square", edge: 4 }; 932 | const expectedPentagon1 = { name: "pentagon", edge: 5 }; 933 | const expectedPentagon2 = { name: "pentagon", edge: 5 }; 934 | const expectedHexagon = { name: "hexagon", edge: 6 }; 935 | 936 | const testArr = utils.merge( 937 | [triangle, pentagon1, pentagon2], 938 | [square, hexagon], 939 | polygon_cmp 940 | ); 941 | const expectedArr = [ 942 | expectedTriangle, 943 | expectedSquare, 944 | expectedPentagon1, 945 | expectedPentagon2, 946 | expectedHexagon, 947 | ]; 948 | expect(testArr.length).toEqual(expectedArr.length); 949 | for (let i = 0; i < testArr.length; ++i) { 950 | expect(testArr[i]).toEqual(expectedArr[i]); 951 | } 952 | }); 953 | 954 | test("mergeDupValIn2ndArrObjArrVal", () => { 955 | const triangle = { name: "triangle", edge: 3 }; 956 | const square1 = { name: "square", edge: 4 }; 957 | const square2 = { name: "square", edge: 4 }; 958 | const pentagon = { name: "pentagon", edge: 5 }; 959 | const hexagon = { name: "hexagon", edge: 6 }; 960 | const expectedTriangle = { name: "triangle", edge: 3 }; 961 | const expectedSquare1 = { name: "square", edge: 4 }; 962 | const expectedSquare2 = { name: "square", edge: 4 }; 963 | const expectedPentagon = { name: "pentagon", edge: 5 }; 964 | const expectedHexagon = { name: "hexagon", edge: 6 }; 965 | 966 | const testArr = utils.merge( 967 | [triangle, pentagon], 968 | [square1, square2, hexagon], 969 | polygon_cmp 970 | ); 971 | const expectedArr = [ 972 | expectedTriangle, 973 | expectedSquare1, 974 | expectedSquare2, 975 | expectedPentagon, 976 | expectedHexagon, 977 | ]; 978 | expect(testArr.length).toEqual(expectedArr.length); 979 | for (let i = 0; i < testArr.length; ++i) { 980 | expect(testArr[i]).toEqual(expectedArr[i]); 981 | } 982 | }); 983 | 984 | test("mergeDupValInTwoArrObjArrVal", () => { 985 | const triangle = { name: "triangle", edge: 3 }; 986 | const square1 = { name: "square", edge: 4 }; 987 | const square2 = { name: "square", edge: 4 }; 988 | const pentagon1 = { name: "pentagon", edge: 5 }; 989 | const pentagon2 = { name: "pentagon", edge: 5 }; 990 | const hexagon = { name: "hexagon", edge: 6 }; 991 | const expectedTriangle = { name: "triangle", edge: 3 }; 992 | const expectedSquare1 = { name: "square", edge: 4 }; 993 | const expectedSquare2 = { name: "square", edge: 4 }; 994 | const expectedPentagon1 = { name: "pentagon", edge: 5 }; 995 | const expectedPentagon2 = { name: "pentagon", edge: 5 }; 996 | const expectedHexagon = { name: "hexagon", edge: 6 }; 997 | 998 | const testArr = utils.merge( 999 | [triangle, pentagon1, pentagon2], 1000 | [square1, square2, hexagon], 1001 | polygon_cmp 1002 | ); 1003 | const expectedArr = [ 1004 | expectedTriangle, 1005 | expectedSquare1, 1006 | expectedSquare2, 1007 | expectedPentagon1, 1008 | expectedPentagon2, 1009 | expectedHexagon, 1010 | ]; 1011 | expect(testArr.length).toEqual(expectedArr.length); 1012 | for (let i = 0; i < testArr.length; ++i) { 1013 | expect(testArr[i]).toEqual(expectedArr[i]); 1014 | } 1015 | }); 1016 | 1017 | test("mergeEmpty2ndArrObjArrVal", () => { 1018 | const triangle = { name: "triangle", edge: 3 }; 1019 | const pentagon = { name: "pentagon", edge: 5 }; 1020 | const expectedTriangle = { name: "triangle", edge: 3 }; 1021 | const expectedPentagon = { name: "pentagon", edge: 5 }; 1022 | 1023 | const testArr = utils.merge([triangle, pentagon], [], polygon_cmp); 1024 | const expectedArr = [expectedTriangle, expectedPentagon]; 1025 | expect(testArr.length).toEqual(expectedArr.length); 1026 | for (let i = 0; i < testArr.length; ++i) { 1027 | expect(testArr[i]).toEqual(expectedArr[i]); 1028 | } 1029 | }); 1030 | 1031 | test("mergeEmpty1stArrObjArrVal", () => { 1032 | const square = { name: "square", edge: 4 }; 1033 | const pentagon = { name: "pentagon", edge: 5 }; 1034 | const expectedSquare = { name: "square", edge: 4 }; 1035 | const expectedPentagon = { name: "pentagon", edge: 5 }; 1036 | 1037 | const testArr = utils.merge([], [square, pentagon], polygon_cmp); 1038 | const expectedArr = [expectedSquare, expectedPentagon]; 1039 | expect(testArr.length).toEqual(expectedArr.length); 1040 | for (let i = 0; i < testArr.length; ++i) { 1041 | expect(testArr[i]).toEqual(expectedArr[i]); 1042 | } 1043 | }); 1044 | 1045 | test("mergeTwoEmptyArrObjArrVal", () => { 1046 | const testArr = utils.merge([], [], polygon_cmp); 1047 | const expectedArr = []; 1048 | expect(testArr.length).toEqual(expectedArr.length); 1049 | for (let i = 0; i < testArr.length; ++i) { 1050 | expect(testArr[i]).toEqual(expectedArr[i]); 1051 | } 1052 | }); 1053 | 1054 | test("mergeNonEmptyArrNoDupVal", () => { 1055 | const testArr = utils.merge([1, 3], [2, 4]); 1056 | const expectedArr = [1, 2, 3, 4]; 1057 | expect(testArr.length).toEqual(expectedArr.length); 1058 | for (let i = 0; i < testArr.length; ++i) { 1059 | expect(testArr[i]).toEqual(expectedArr[i]); 1060 | } 1061 | }); 1062 | 1063 | test("mergeDupValIn1stArr", () => { 1064 | const testArr = utils.merge([1, 3, 3], [2, 4]); 1065 | const expectedArr = [1, 2, 3, 3, 4]; 1066 | expect(testArr.length).toEqual(expectedArr.length); 1067 | for (let i = 0; i < testArr.length; ++i) { 1068 | expect(testArr[i]).toEqual(expectedArr[i]); 1069 | } 1070 | }); 1071 | 1072 | test("mergeDupValIn2ndArr", () => { 1073 | const testArr = utils.merge([1, 3], [2, 2, 4]); 1074 | const expectedArr = [1, 2, 2, 3, 4]; 1075 | expect(testArr.length).toEqual(expectedArr.length); 1076 | for (let i = 0; i < testArr.length; ++i) { 1077 | expect(testArr[i]).toEqual(expectedArr[i]); 1078 | } 1079 | }); 1080 | 1081 | test("mergeDupValInTwoArr", () => { 1082 | const testArr = utils.merge([1, 3, 3], [2, 2, 4]); 1083 | const expectedArr = [1, 2, 2, 3, 3, 4]; 1084 | expect(testArr.length).toEqual(expectedArr.length); 1085 | for (let i = 0; i < testArr.length; ++i) { 1086 | expect(testArr[i]).toEqual(expectedArr[i]); 1087 | } 1088 | }); 1089 | 1090 | test("mergeEmpty2ndArr", () => { 1091 | const testArr = utils.merge([1, 3], []); 1092 | const expectedArr = [1, 3]; 1093 | expect(testArr.length).toEqual(expectedArr.length); 1094 | for (let i = 0; i < testArr.length; ++i) { 1095 | expect(testArr[i]).toEqual(expectedArr[i]); 1096 | } 1097 | }); 1098 | 1099 | test("mergeEmpty1stArr", () => { 1100 | const testArr = utils.merge([], [2, 3]); 1101 | const expectedArr = [2, 3]; 1102 | expect(testArr.length).toEqual(expectedArr.length); 1103 | for (let i = 0; i < testArr.length; ++i) { 1104 | expect(testArr[i]).toEqual(expectedArr[i]); 1105 | } 1106 | }); 1107 | 1108 | test("mergeTwoEmptyArr", () => { 1109 | const testArr = utils.merge([], []); 1110 | const expectedArr = []; 1111 | expect(testArr.length).toEqual(expectedArr.length); 1112 | for (let i = 0; i < testArr.length; ++i) { 1113 | expect(testArr[i]).toEqual(expectedArr[i]); 1114 | } 1115 | }); 1116 | }); 1117 | 1118 | describe("inplace_merge", () => { 1119 | test("inplace_mergeNoDupValTwoArrObjArrVal", () => { 1120 | const triangle = { name: "triangle", edge: 3 }; 1121 | const square = { name: "square", edge: 4 }; 1122 | const pentagon = { name: "pentagon", edge: 5 }; 1123 | const hexagon = { name: "hexagon", edge: 6 }; 1124 | const expectedTriangle = { name: "triangle", edge: 3 }; 1125 | const expectedSquare = { name: "square", edge: 4 }; 1126 | const expectedPentagon = { name: "pentagon", edge: 5 }; 1127 | const expectedHexagon = { name: "hexagon", edge: 6 }; 1128 | 1129 | const testArr = [triangle, pentagon, square, hexagon]; 1130 | utils.inplace_merge(testArr, 2, polygon_cmp); 1131 | const expectedArr = [ 1132 | expectedTriangle, 1133 | expectedSquare, 1134 | expectedPentagon, 1135 | expectedHexagon, 1136 | ]; 1137 | expect(testArr.length).toEqual(expectedArr.length); 1138 | for (let i = 0; i < testArr.length; ++i) { 1139 | expect(testArr[i]).toEqual(expectedArr[i]); 1140 | } 1141 | }); 1142 | 1143 | test("inplace_mergeDupValIn1stArrObjArrVal", () => { 1144 | const triangle = { name: "triangle", edge: 3 }; 1145 | const square = { name: "square", edge: 4 }; 1146 | const pentagon1 = { name: "pentagon", edge: 5 }; 1147 | const pentagon2 = { name: "pentagon", edge: 5 }; 1148 | const hexagon = { name: "hexagon", edge: 6 }; 1149 | const expectedTriangle = { name: "triangle", edge: 3 }; 1150 | const expectedSquare = { name: "square", edge: 4 }; 1151 | const expectedPentagon1 = { name: "pentagon", edge: 5 }; 1152 | const expectedPentagon2 = { name: "pentagon", edge: 5 }; 1153 | const expectedHexagon = { name: "hexagon", edge: 6 }; 1154 | 1155 | const testArr = [triangle, pentagon1, pentagon2, square, hexagon]; 1156 | utils.inplace_merge(testArr, 3, polygon_cmp); 1157 | 1158 | const expectedArr = [ 1159 | expectedTriangle, 1160 | expectedSquare, 1161 | expectedPentagon1, 1162 | expectedPentagon2, 1163 | expectedHexagon, 1164 | ]; 1165 | expect(testArr.length).toEqual(expectedArr.length); 1166 | for (let i = 0; i < testArr.length; ++i) { 1167 | expect(testArr[i]).toEqual(expectedArr[i]); 1168 | } 1169 | }); 1170 | 1171 | test("inplace_mergeDupValIn2ndArrObjArrVal", () => { 1172 | const triangle = { name: "triangle", edge: 3 }; 1173 | const square1 = { name: "square", edge: 4 }; 1174 | const square2 = { name: "square", edge: 4 }; 1175 | const pentagon = { name: "pentagon", edge: 5 }; 1176 | const hexagon = { name: "hexagon", edge: 6 }; 1177 | const expectedTriangle = { name: "triangle", edge: 3 }; 1178 | const expectedSquare1 = { name: "square", edge: 4 }; 1179 | const expectedSquare2 = { name: "square", edge: 4 }; 1180 | const expectedPentagon = { name: "pentagon", edge: 5 }; 1181 | const expectedHexagon = { name: "hexagon", edge: 6 }; 1182 | 1183 | const testArr = [triangle, pentagon, square1, square2, hexagon]; 1184 | utils.inplace_merge(testArr, 2, polygon_cmp); 1185 | 1186 | const expectedArr = [ 1187 | expectedTriangle, 1188 | expectedSquare1, 1189 | expectedSquare2, 1190 | expectedPentagon, 1191 | expectedHexagon, 1192 | ]; 1193 | expect(testArr.length).toEqual(expectedArr.length); 1194 | for (let i = 0; i < testArr.length; ++i) { 1195 | expect(testArr[i]).toEqual(expectedArr[i]); 1196 | } 1197 | }); 1198 | 1199 | test("inplace_mergeDupValInTwoArrObjArrVal", () => { 1200 | const triangle = { name: "triangle", edge: 3 }; 1201 | const square1 = { name: "square", edge: 4 }; 1202 | const pentagon1 = { name: "pentagon", edge: 5 }; 1203 | const square2 = { name: "square", edge: 4 }; 1204 | const pentagon2 = { name: "pentagon", edge: 5 }; 1205 | const hexagon = { name: "hexagon", edge: 6 }; 1206 | const expectedTriangle = { name: "triangle", edge: 3 }; 1207 | const expectedSquare1 = { name: "square", edge: 4 }; 1208 | const expectedPentagon1 = { name: "pentagon", edge: 5 }; 1209 | const expectedSquare2 = { name: "square", edge: 4 }; 1210 | const expectedPentagon2 = { name: "pentagon", edge: 5 }; 1211 | const expectedHexagon = { name: "hexagon", edge: 6 }; 1212 | 1213 | const testArr = [triangle, pentagon1, pentagon2, square1, square2, hexagon]; 1214 | utils.inplace_merge(testArr, 3, polygon_cmp); 1215 | const expectedArr = [ 1216 | expectedTriangle, 1217 | expectedSquare1, 1218 | expectedSquare2, 1219 | expectedPentagon1, 1220 | expectedPentagon2, 1221 | expectedHexagon, 1222 | ]; 1223 | expect(testArr.length).toEqual(expectedArr.length); 1224 | for (let i = 0; i < testArr.length; ++i) { 1225 | expect(testArr[i]).toEqual(expectedArr[i]); 1226 | } 1227 | }); 1228 | 1229 | test("inplace_mergeNo1stArrObjArrVal", () => { 1230 | const square1 = { name: "square", edge: 4 }; 1231 | const square2 = { name: "square", edge: 4 }; 1232 | const hexagon = { name: "hexagon", edge: 6 }; 1233 | const expectedSquare1 = { name: "square", edge: 4 }; 1234 | const expectedSquare2 = { name: "square", edge: 4 }; 1235 | const expectedHexagon = { name: "hexagon", edge: 6 }; 1236 | 1237 | const testArr = [square1, square2, hexagon]; 1238 | utils.inplace_merge(testArr, 0, polygon_cmp); 1239 | 1240 | const expectedArr = [expectedSquare1, expectedSquare2, expectedHexagon]; 1241 | expect(testArr.length).toEqual(expectedArr.length); 1242 | for (let i = 0; i < testArr.length; ++i) { 1243 | expect(testArr[i]).toEqual(expectedArr[i]); 1244 | } 1245 | }); 1246 | 1247 | test("inplace_mergeDupValExistInTwoArrObjArrVal", () => { 1248 | const square1 = { name: "square", edge: 4 }; 1249 | const square2 = { name: "square", edge: 4 }; 1250 | const hexagon = { name: "hexagon", edge: 6 }; 1251 | const expectedSquare1 = { name: "square", edge: 4 }; 1252 | const expectedSquare2 = { name: "square", edge: 4 }; 1253 | const expectedHexagon = { name: "hexagon", edge: 6 }; 1254 | 1255 | const testArr = [square1, square2, hexagon]; 1256 | utils.inplace_merge(testArr, 1, polygon_cmp); 1257 | const expectedArr = [expectedSquare1, expectedSquare2, expectedHexagon]; 1258 | expect(testArr.length).toEqual(expectedArr.length); 1259 | for (let i = 0; i < testArr.length; ++i) { 1260 | expect(testArr[i]).toEqual(expectedArr[i]); 1261 | } 1262 | }); 1263 | 1264 | test("inplace_mergeNo2ndArrObjArrVal", () => { 1265 | const square1 = { name: "square", edge: 4 }; 1266 | const square2 = { name: "square", edge: 4 }; 1267 | const hexagon = { name: "hexagon", edge: 6 }; 1268 | const expectedSquare1 = { name: "square", edge: 4 }; 1269 | const expectedSquare2 = { name: "square", edge: 4 }; 1270 | const expectedHexagon = { name: "hexagon", edge: 6 }; 1271 | 1272 | const testArr = [square1, square2, hexagon]; 1273 | utils.inplace_merge(testArr, 3, polygon_cmp); 1274 | const expectedArr = [expectedSquare1, expectedSquare2, expectedHexagon]; 1275 | expect(testArr.length).toEqual(expectedArr.length); 1276 | for (let i = 0; i < testArr.length; ++i) { 1277 | expect(testArr[i]).toEqual(expectedArr[i]); 1278 | } 1279 | }); 1280 | 1281 | test("inplace_mergeNoDupValTwoArr", () => { 1282 | const testArr = [1, 3, 2, 4]; 1283 | utils.inplace_merge(testArr, 2); 1284 | const expectedArr = [1, 2, 3, 4]; 1285 | expect(testArr.length).toEqual(expectedArr.length); 1286 | for (let i = 0; i < testArr.length; ++i) { 1287 | expect(testArr[i]).toEqual(expectedArr[i]); 1288 | } 1289 | }); 1290 | 1291 | test("inplace_mergeDupValIn1stArr", () => { 1292 | const testArr = [1, 3, 3, 2, 4]; 1293 | utils.inplace_merge(testArr, 3); 1294 | 1295 | const expectedArr = [1, 2, 3, 3, 4]; 1296 | expect(testArr.length).toEqual(expectedArr.length); 1297 | for (let i = 0; i < testArr.length; ++i) { 1298 | expect(testArr[i]).toEqual(expectedArr[i]); 1299 | } 1300 | }); 1301 | 1302 | test("inplace_mergeDupValIn2ndArr", () => { 1303 | const testArr = [1, 3, 2, 2, 4]; 1304 | utils.inplace_merge(testArr, 2); 1305 | 1306 | const expectedArr = [1, 2, 2, 3, 4]; 1307 | expect(testArr.length).toEqual(expectedArr.length); 1308 | for (let i = 0; i < testArr.length; ++i) { 1309 | expect(testArr[i]).toEqual(expectedArr[i]); 1310 | } 1311 | }); 1312 | 1313 | test("inplace_mergeDupValInTwoArr", () => { 1314 | const testArr = [1, 3, 3, 2, 2, 4]; 1315 | utils.inplace_merge(testArr, 3); 1316 | const expectedArr = [1, 2, 2, 3, 3, 4]; 1317 | expect(testArr.length).toEqual(expectedArr.length); 1318 | for (let i = 0; i < testArr.length; ++i) { 1319 | expect(testArr[i]).toEqual(expectedArr[i]); 1320 | } 1321 | }); 1322 | 1323 | test("inplace_mergeNo1stArr", () => { 1324 | const testArr = [2, 2, 4]; 1325 | utils.inplace_merge(testArr, 0); 1326 | 1327 | const expectedArr = [2, 2, 4]; 1328 | expect(testArr.length).toEqual(expectedArr.length); 1329 | for (let i = 0; i < testArr.length; ++i) { 1330 | expect(testArr[i]).toEqual(expectedArr[i]); 1331 | } 1332 | }); 1333 | 1334 | test("inplace_mergeDupValExistInTwoArr", () => { 1335 | const testArr = [2, 2, 4]; 1336 | utils.inplace_merge(testArr, 1); 1337 | const expectedArr = [2, 2, 4]; 1338 | expect(testArr.length).toEqual(expectedArr.length); 1339 | for (let i = 0; i < testArr.length; ++i) { 1340 | expect(testArr[i]).toEqual(expectedArr[i]); 1341 | } 1342 | }); 1343 | 1344 | test("inplace_mergeNo2ndArr", () => { 1345 | const testArr = [2, 2, 4]; 1346 | utils.inplace_merge(testArr, 3); 1347 | const expectedArr = [2, 2, 4]; 1348 | expect(testArr.length).toEqual(expectedArr.length); 1349 | for (let i = 0; i < testArr.length; ++i) { 1350 | expect(testArr[i]).toEqual(expectedArr[i]); 1351 | } 1352 | }); 1353 | }); 1354 | 1355 | describe("includes", () => { 1356 | test("includesNoDupVal2ndArrElemAsSomeOf1stArrElemObjArrVal", () => { 1357 | const triangle = { name: "triangle", edge: 3 }; 1358 | const square1 = { name: "square", edge: 4 }; 1359 | const square2 = { name: "square", edge: 4 }; 1360 | const pentagon = { name: "pentagon", edge: 5 }; 1361 | const hexagon = { name: "hexagon", edge: 6 }; 1362 | 1363 | expect( 1364 | utils.includes( 1365 | [triangle, square1, pentagon, hexagon], 1366 | [square2], 1367 | polygon_cmp 1368 | ) 1369 | ).toEqual(true); 1370 | }); 1371 | 1372 | test("includesNoDupValAll2ndArrElemNotIn1stArrObjArrVal", () => { 1373 | const triangle = { name: "triangle", edge: 3 }; 1374 | const square = { name: "square", edge: 4 }; 1375 | const pentagon = { name: "pentagon", edge: 5 }; 1376 | const hexagon = { name: "hexagon", edge: 6 }; 1377 | const heptagon = { name: "heptagon", edge: 7 }; 1378 | 1379 | expect( 1380 | utils.includes( 1381 | [triangle, square, pentagon, hexagon], 1382 | [heptagon], 1383 | polygon_cmp 1384 | ) 1385 | ).toEqual(false); 1386 | }); 1387 | 1388 | test("includes2ndArrEmptyObjArrVal", () => { 1389 | const triangle = { name: "triangle", edge: 3 }; 1390 | const square = { name: "square", edge: 4 }; 1391 | const pentagon = { name: "pentagon", edge: 5 }; 1392 | const hexagon = { name: "hexagon", edge: 6 }; 1393 | 1394 | expect( 1395 | utils.includes([triangle, square, pentagon, hexagon], [], polygon_cmp) 1396 | ).toEqual(true); 1397 | }); 1398 | 1399 | test("includesTwoArrEmptyObjArrVal", () => { 1400 | expect(utils.includes([], [], polygon_cmp)).toEqual(true); 1401 | }); 1402 | 1403 | test("includes1stArrEmptyObjArrVal", () => { 1404 | const heptagon = { name: "heptagon", edge: 7 }; 1405 | 1406 | expect(utils.includes([], [heptagon], polygon_cmp)).toEqual(false); 1407 | }); 1408 | 1409 | test("includesDupVal2ndArrElemAsSomeOf1stArrElemObjArrVal", () => { 1410 | const triangle = { name: "triangle", edge: 3 }; 1411 | const square1 = { name: "square", edge: 4 }; 1412 | const square2 = { name: "square", edge: 4 }; 1413 | const square3 = { name: "square", edge: 4 }; 1414 | const square4 = { name: "square", edge: 4 }; 1415 | const pentagon = { name: "pentagon", edge: 5 }; 1416 | const hexagon = { name: "hexagon", edge: 6 }; 1417 | 1418 | expect( 1419 | utils.includes( 1420 | [triangle, square1, square2, pentagon, hexagon], 1421 | [square3, square4], 1422 | polygon_cmp 1423 | ) 1424 | ).toEqual(true); 1425 | }); 1426 | 1427 | test("includesDupValAndNonDupVal2ndArrElemAsSomeOf1stArrElemObjArrVal", () => { 1428 | const triangle = { name: "triangle", edge: 3 }; 1429 | const square1 = { name: "square", edge: 4 }; 1430 | const square2 = { name: "square", edge: 4 }; 1431 | const square3 = { name: "square", edge: 4 }; 1432 | const square4 = { name: "square", edge: 4 }; 1433 | const square5 = { name: "square", edge: 4 }; 1434 | const square6 = { name: "square", edge: 4 }; 1435 | const pentagon1 = { name: "pentagon", edge: 5 }; 1436 | const pentagon2 = { name: "pentagon", edge: 5 }; 1437 | const hexagon = { name: "hexagon", edge: 6 }; 1438 | 1439 | expect( 1440 | utils.includes( 1441 | [triangle, square1, square2, square3, square4, pentagon1, hexagon], 1442 | [square5, square6, pentagon2], 1443 | polygon_cmp 1444 | ) 1445 | ).toEqual(true); 1446 | }); 1447 | 1448 | test("includes3DupValIn2ndArrAnd2DupValIn1stArrObjArrVal", () => { 1449 | const triangle = { name: "triangle", edge: 3 }; 1450 | const square1 = { name: "square", edge: 4 }; 1451 | const square2 = { name: "square", edge: 4 }; 1452 | const square3 = { name: "square", edge: 4 }; 1453 | const square4 = { name: "square", edge: 4 }; 1454 | const square5 = { name: "square", edge: 4 }; 1455 | const pentagon = { name: "pentagon", edge: 5 }; 1456 | const hexagon = { name: "hexagon", edge: 6 }; 1457 | 1458 | expect( 1459 | utils.includes( 1460 | [triangle, square1, square2, pentagon, hexagon], 1461 | [square3, square4, square5], 1462 | polygon_cmp 1463 | ) 1464 | ).toEqual(false); 1465 | }); 1466 | 1467 | test("includes2DupValIn2ndArrAnd1DupValIn1stArrPlus1NonDupValIn2ndArrObjArrVal", () => { 1468 | const triangle = { name: "triangle", edge: 3 }; 1469 | const square1 = { name: "square", edge: 4 }; 1470 | const square2 = { name: "square", edge: 4 }; 1471 | const square3 = { name: "square", edge: 4 }; 1472 | const square4 = { name: "square", edge: 4 }; 1473 | const square5 = { name: "square", edge: 4 }; 1474 | const square6 = { name: "square", edge: 4 }; 1475 | const pentagon = { name: "pentagon", edge: 5 }; 1476 | const hexagon = { name: "hexagon", edge: 6 }; 1477 | const heptagon = { name: "heptagon", edge: 7 }; 1478 | 1479 | expect( 1480 | utils.includes( 1481 | [triangle, square1, square2, square3, square4, pentagon, hexagon], 1482 | [square5, square6, heptagon], 1483 | polygon_cmp 1484 | ) 1485 | ).toEqual(false); 1486 | }); 1487 | 1488 | test("includesTwoArraySame", () => { 1489 | const triangle1 = { name: "triangle", edge: 3 }; 1490 | const triangle2 = { name: "triangle", edge: 3 }; 1491 | const square1 = { name: "square", edge: 4 }; 1492 | const square2 = { name: "square", edge: 4 }; 1493 | const square3 = { name: "square", edge: 4 }; 1494 | const square4 = { name: "square", edge: 4 }; 1495 | const square5 = { name: "square", edge: 4 }; 1496 | const square6 = { name: "square", edge: 4 }; 1497 | const square7 = { name: "square", edge: 4 }; 1498 | const square8 = { name: "square", edge: 4 }; 1499 | const pentagon1 = { name: "pentagon", edge: 5 }; 1500 | const pentagon2 = { name: "pentagon", edge: 5 }; 1501 | const hexagon1 = { name: "hexagon", edge: 6 }; 1502 | const hexagon2 = { name: "hexagon", edge: 6 }; 1503 | const hexagon3 = { name: "hexagon", edge: 6 }; 1504 | const hexagon4 = { name: "hexagon", edge: 6 }; 1505 | const hexagon5 = { name: "hexagon", edge: 6 }; 1506 | const hexagon6 = { name: "hexagon", edge: 6 }; 1507 | 1508 | expect( 1509 | utils.includes( 1510 | [ 1511 | triangle1, 1512 | square1, 1513 | square2, 1514 | square3, 1515 | square4, 1516 | pentagon1, 1517 | hexagon1, 1518 | hexagon2, 1519 | hexagon3, 1520 | ], 1521 | [ 1522 | triangle2, 1523 | square5, 1524 | square6, 1525 | square7, 1526 | square8, 1527 | pentagon2, 1528 | hexagon4, 1529 | hexagon5, 1530 | hexagon6, 1531 | ], 1532 | polygon_cmp 1533 | ) 1534 | ).toEqual(true); 1535 | }); 1536 | 1537 | test("includesAllElemIn1stArrIn2ndArrAndOneElemIn2ndArrGreaterThanAllIn1stArrObjArrVal", () => { 1538 | const triangle1 = { name: "triangle", edge: 3 }; 1539 | const triangle2 = { name: "triangle", edge: 3 }; 1540 | const square1 = { name: "square", edge: 4 }; 1541 | const square2 = { name: "square", edge: 4 }; 1542 | const square3 = { name: "square", edge: 4 }; 1543 | const square4 = { name: "square", edge: 4 }; 1544 | const square5 = { name: "square", edge: 4 }; 1545 | const square6 = { name: "square", edge: 4 }; 1546 | const square7 = { name: "square", edge: 4 }; 1547 | const square8 = { name: "square", edge: 4 }; 1548 | const pentagon1 = { name: "pentagon", edge: 5 }; 1549 | const pentagon2 = { name: "pentagon", edge: 5 }; 1550 | const hexagon1 = { name: "hexagon", edge: 6 }; 1551 | const hexagon2 = { name: "hexagon", edge: 6 }; 1552 | const heptagon = { name: "heptagon", edge: 7 }; 1553 | 1554 | expect( 1555 | utils.includes( 1556 | [triangle1, square1, square2, square3, square4, pentagon1, hexagon1], 1557 | [ 1558 | triangle2, 1559 | square5, 1560 | square6, 1561 | square7, 1562 | square8, 1563 | pentagon2, 1564 | hexagon2, 1565 | heptagon, 1566 | ], 1567 | polygon_cmp 1568 | ) 1569 | ).toEqual(false); 1570 | }); 1571 | 1572 | test("includesAllElemIn1stArrIn2ndArrAndOneElemIn2ndArrInRangeOf1stArrElemObjArrVal", () => { 1573 | const triangle1 = { name: "triangle", edge: 3 }; 1574 | const triangle2 = { name: "triangle", edge: 3 }; 1575 | const square1 = { name: "square", edge: 4 }; 1576 | const square2 = { name: "square", edge: 4 }; 1577 | const square3 = { name: "square", edge: 4 }; 1578 | const square4 = { name: "square", edge: 4 }; 1579 | const square5 = { name: "square", edge: 4 }; 1580 | const square6 = { name: "square", edge: 4 }; 1581 | const heptagon = { name: "heptagon", edge: 5 }; 1582 | const enneagon1 = { name: "enneagon", edge: 7 }; 1583 | const enneagon2 = { name: "enneagon", edge: 7 }; 1584 | const decagon1 = { name: "decagon", edge: 8 }; 1585 | const decagon2 = { name: "decagon", edge: 8 }; 1586 | const hendecagon1 = { name: "hendecagon", edge: 9 }; 1587 | const hendecagon2 = { name: "hendecagon", edge: 9 }; 1588 | const hendecagon3 = { name: "hendecagon", edge: 9 }; 1589 | const hendecagon4 = { name: "hendecagon", edge: 9 }; 1590 | 1591 | expect( 1592 | utils.includes( 1593 | [ 1594 | triangle1, 1595 | square1, 1596 | square2, 1597 | square3, 1598 | enneagon1, 1599 | decagon1, 1600 | hendecagon1, 1601 | hendecagon2, 1602 | ], 1603 | [ 1604 | triangle2, 1605 | square4, 1606 | square5, 1607 | square6, 1608 | heptagon, 1609 | enneagon2, 1610 | decagon2, 1611 | hendecagon3, 1612 | hendecagon4, 1613 | ], 1614 | polygon_cmp 1615 | ) 1616 | ).toEqual(false); 1617 | }); 1618 | 1619 | test("includesAllElemIn1stArrIn2ndArrAndOneElemIn2ndArrSmallerThanAllIn1stArrObjArrVal", () => { 1620 | const digon = { name: "digon", edge: 2 }; 1621 | const triangle1 = { name: "triangle", edge: 3 }; 1622 | const triangle2 = { name: "triangle", edge: 3 }; 1623 | const square1 = { name: "square", edge: 4 }; 1624 | const square2 = { name: "square", edge: 4 }; 1625 | const square3 = { name: "square", edge: 4 }; 1626 | const square4 = { name: "square", edge: 4 }; 1627 | const square5 = { name: "square", edge: 4 }; 1628 | const square6 = { name: "square", edge: 4 }; 1629 | const enneagon1 = { name: "enneagon", edge: 7 }; 1630 | const enneagon2 = { name: "enneagon", edge: 7 }; 1631 | const decagon1 = { name: "decagon", edge: 8 }; 1632 | const decagon2 = { name: "decagon", edge: 8 }; 1633 | const hendecagon1 = { name: "hendecagon", edge: 9 }; 1634 | const hendecagon2 = { name: "hendecagon", edge: 9 }; 1635 | const hendecagon3 = { name: "hendecagon", edge: 9 }; 1636 | const hendecagon4 = { name: "hendecagon", edge: 9 }; 1637 | 1638 | expect( 1639 | utils.includes( 1640 | [ 1641 | triangle1, 1642 | square1, 1643 | square2, 1644 | square3, 1645 | enneagon1, 1646 | decagon1, 1647 | hendecagon1, 1648 | hendecagon2, 1649 | ], 1650 | [ 1651 | digon, 1652 | triangle2, 1653 | square4, 1654 | square5, 1655 | square6, 1656 | enneagon2, 1657 | decagon2, 1658 | hendecagon3, 1659 | hendecagon4, 1660 | ], 1661 | polygon_cmp 1662 | ) 1663 | ).toEqual(false); 1664 | }); 1665 | 1666 | test("includesAllElemIn1stArrIn2ndArrAnd2DupValIn2ndArrAnd1DupValIn1stArrObjArrVal", () => { 1667 | const triangle1 = { name: "triangle", edge: 3 }; 1668 | const triangle2 = { name: "triangle", edge: 3 }; 1669 | const square1 = { name: "square", edge: 4 }; 1670 | const square2 = { name: "square", edge: 4 }; 1671 | const square3 = { name: "square", edge: 4 }; 1672 | const square4 = { name: "square", edge: 4 }; 1673 | const square5 = { name: "square", edge: 4 }; 1674 | const square6 = { name: "square", edge: 4 }; 1675 | const enneagon1 = { name: "enneagon", edge: 7 }; 1676 | const enneagon2 = { name: "enneagon", edge: 7 }; 1677 | const enneagon3 = { name: "enneagon", edge: 7 }; 1678 | const decagon1 = { name: "decagon", edge: 8 }; 1679 | const decagon2 = { name: "decagon", edge: 8 }; 1680 | const hendecagon1 = { name: "hendecagon", edge: 9 }; 1681 | const hendecagon2 = { name: "hendecagon", edge: 9 }; 1682 | const hendecagon3 = { name: "hendecagon", edge: 9 }; 1683 | const hendecagon4 = { name: "hendecagon", edge: 9 }; 1684 | 1685 | expect( 1686 | utils.includes( 1687 | [ 1688 | triangle1, 1689 | square1, 1690 | square2, 1691 | square3, 1692 | enneagon1, 1693 | decagon1, 1694 | hendecagon1, 1695 | hendecagon2, 1696 | ], 1697 | [ 1698 | triangle2, 1699 | square4, 1700 | square5, 1701 | square6, 1702 | enneagon2, 1703 | enneagon3, 1704 | decagon2, 1705 | hendecagon3, 1706 | hendecagon4, 1707 | ], 1708 | polygon_cmp 1709 | ) 1710 | ).toEqual(false); 1711 | }); 1712 | 1713 | test("includesNoDupVal2ndArrElemAsSomeOf1stArrElem", () => { 1714 | expect(utils.includes([1, 2, 3, 4], [2])).toEqual(true); 1715 | }); 1716 | 1717 | test("includesNoDupValAll2ndArrElemNotIn1stArr", () => { 1718 | expect(utils.includes([1, 2, 3, 4], [5])).toEqual(false); 1719 | }); 1720 | 1721 | test("includes2ndArrEmpty", () => { 1722 | expect(utils.includes([1, 2, 3, 4], [])).toEqual(true); 1723 | }); 1724 | 1725 | test("includesTwoArrEmpty", () => { 1726 | expect(utils.includes([], [])).toEqual(true); 1727 | }); 1728 | 1729 | test("includes1stArrEmpty", () => { 1730 | expect(utils.includes([], [5])).toEqual(false); 1731 | }); 1732 | 1733 | test("includesDupVal2ndArrElemAsSomeOf1stArrElem", () => { 1734 | expect(utils.includes([1, 2, 2, 3, 4], [2, 2])).toEqual(true); 1735 | }); 1736 | 1737 | test("includesDupValAndNonDupVal2ndArrElemAsSomeOf1stArrElem", () => { 1738 | expect(utils.includes([1, 2, 2, 2, 2, 3, 4], [2, 2, 3])).toEqual(true); 1739 | }); 1740 | 1741 | test("includes3DupValIn2ndArrAnd2DupValIn1stArr", () => { 1742 | expect(utils.includes([1, 2, 2, 3, 4], [2, 2, 2])).toEqual(false); 1743 | }); 1744 | 1745 | test("includes2DupValIn2ndArrAnd1DupValIn1stArrPlus1NonDupValIn2ndArr", () => { 1746 | expect(utils.includes([1, 2, 2, 2, 2, 3, 4], [2, 2, 5])).toEqual(false); 1747 | }); 1748 | 1749 | test("includesTwoArraySame", () => { 1750 | expect( 1751 | utils.includes([1, 2, 2, 2, 2, 3, 4, 4, 4], [1, 2, 2, 2, 2, 3, 4, 4, 4]) 1752 | ).toEqual(true); 1753 | }); 1754 | 1755 | test("includesAllElemIn1stArrIn2ndArrAndOneElemIn2ndArrGreaterThanAllIn1stArr", () => { 1756 | expect( 1757 | utils.includes([1, 2, 2, 2, 2, 3, 4], [1, 2, 2, 2, 2, 3, 4, 5]) 1758 | ).toEqual(false); 1759 | }); 1760 | 1761 | test("includesAllElemIn1stArrIn2ndArrAndOneElemIn2ndArrInRangeOf1stArrElem", () => { 1762 | expect( 1763 | utils.includes([1, 2, 2, 2, 7, 8, 9, 9], [1, 2, 2, 2, 5, 7, 8, 9, 9]) 1764 | ).toEqual(false); 1765 | }); 1766 | 1767 | test("includesAllElemIn1stArrIn2ndArrAndOneElemIn2ndArrSmallerThanAllIn1stArr", () => { 1768 | expect( 1769 | utils.includes([1, 2, 2, 2, 7, 8, 9, 9], [0, 1, 2, 2, 2, 7, 8, 9, 9]) 1770 | ).toEqual(false); 1771 | }); 1772 | 1773 | test("includesAllElemIn1stArrIn2ndArrAnd2DupValIn2ndArrAnd1DupValIn1stArr", () => { 1774 | expect( 1775 | utils.includes([1, 2, 2, 2, 7, 8, 9, 9], [1, 2, 2, 2, 7, 7, 8, 9, 9]) 1776 | ).toEqual(false); 1777 | }); 1778 | }); 1779 | 1780 | describe("insert", () => { 1781 | test("insertInArrNoDupValObjArrVal", () => { 1782 | const triangle = { name: "triangle", edge: 3 }; 1783 | const square = { name: "square", edge: 4 }; 1784 | const pentagon = { name: "pentagon", edge: 5 }; 1785 | const hexagon = { name: "hexagon", edge: 6 }; 1786 | const heptagon = { name: "heptagon", edge: 7 }; 1787 | const expectedTriangle = { name: "triangle", edge: 3 }; 1788 | const expectedSquare = { name: "square", edge: 4 }; 1789 | const expectedPentagon = { name: "pentagon", edge: 5 }; 1790 | const expectedHexagon = { name: "hexagon", edge: 6 }; 1791 | const expectedHeptagon = { name: "heptagon", edge: 7 }; 1792 | 1793 | const testArr = [triangle, square, hexagon, heptagon]; 1794 | utils.insert(testArr, pentagon, polygon_cmp); 1795 | const expectedArr = [ 1796 | expectedTriangle, 1797 | expectedSquare, 1798 | expectedPentagon, 1799 | expectedHexagon, 1800 | expectedHeptagon, 1801 | ]; 1802 | expect(testArr.length).toEqual(expectedArr.length); 1803 | for (let i = 0; i < testArr.length; ++i) { 1804 | expect(testArr[i]).toEqual(expectedArr[i]); 1805 | } 1806 | }); 1807 | 1808 | test("insertEmptyArrObjArrVal", () => { 1809 | const pentagon = { name: "pentagon", edge: 5 }; 1810 | const expectedPentagon = { name: "pentagon", edge: 5 }; 1811 | 1812 | const testArr = []; 1813 | utils.insert(testArr, pentagon, polygon_cmp); 1814 | const expectedArr = [expectedPentagon]; 1815 | expect(testArr.length).toEqual(expectedArr.length); 1816 | for (let i = 0; i < testArr.length; ++i) { 1817 | expect(testArr[i]).toEqual(expectedArr[i]); 1818 | } 1819 | }); 1820 | 1821 | test("insertToFrontOfArrObjArrVal", () => { 1822 | const digon = { name: "digon", edge: 2 }; 1823 | const triangle = { name: "triangle", edge: 3 }; 1824 | const square = { name: "square", edge: 4 }; 1825 | const hexagon = { name: "hexagon", edge: 6 }; 1826 | const heptagon = { name: "heptagon", edge: 7 }; 1827 | const octagon = { name: "octagon", edge: 8 }; 1828 | const enneagon = { name: "enneagon", edge: 9 }; 1829 | const decagon = { name: "decagon", edge: 10 }; 1830 | 1831 | const expectedDigon = { name: "digon", edge: 2 }; 1832 | const expectedTriangle = { name: "triangle", edge: 3 }; 1833 | const expectedSquare = { name: "square", edge: 4 }; 1834 | const expectedHexagon = { name: "hexagon", edge: 6 }; 1835 | const expectedHeptagon = { name: "heptagon", edge: 7 }; 1836 | const expectedOctagon = { name: "octagon", edge: 8 }; 1837 | const expectedEnneagon = { name: "enneagon", edge: 9 }; 1838 | const expectedDecagon = { name: "decagon", edge: 10 }; 1839 | 1840 | const testArr = [ 1841 | triangle, 1842 | square, 1843 | hexagon, 1844 | heptagon, 1845 | octagon, 1846 | enneagon, 1847 | decagon, 1848 | ]; 1849 | utils.insert(testArr, digon, polygon_cmp); 1850 | 1851 | const expectedArr = [ 1852 | expectedDigon, 1853 | expectedTriangle, 1854 | expectedSquare, 1855 | expectedHexagon, 1856 | expectedHeptagon, 1857 | expectedOctagon, 1858 | expectedEnneagon, 1859 | expectedDecagon, 1860 | ]; 1861 | expect(testArr.length).toEqual(expectedArr.length); 1862 | for (let i = 0; i < testArr.length; ++i) { 1863 | expect(testArr[i]).toEqual(expectedArr[i]); 1864 | } 1865 | }); 1866 | 1867 | test("insertNonDupValToMidOfArrObjArrVal", () => { 1868 | const triangle1 = { name: "triangle", edge: 3 }; 1869 | const triangle2 = { name: "triangle", edge: 3 }; 1870 | const triangle3 = { name: "triangle", edge: 3 }; 1871 | const square = { name: "square", edge: 4 }; 1872 | const pentagon = { name: "pentagon", edge: 5 }; 1873 | const hexagon1 = { name: "hexagon", edge: 6 }; 1874 | const hexagon2 = { name: "hexagon", edge: 6 }; 1875 | const hexagon3 = { name: "hexagon", edge: 6 }; 1876 | const hexagon4 = { name: "hexagon", edge: 6 }; 1877 | const heptagon = { name: "heptagon", edge: 7 }; 1878 | const octagon = { name: "octagon", edge: 8 }; 1879 | const enneagon = { name: "enneagon", edge: 9 }; 1880 | const decagon = { name: "decagon", edge: 10 }; 1881 | const expectedTriangle1 = { name: "triangle", edge: 3 }; 1882 | const expectedTriangle2 = { name: "triangle", edge: 3 }; 1883 | const expectedTriangle3 = { name: "triangle", edge: 3 }; 1884 | const expectedSquare = { name: "square", edge: 4 }; 1885 | const expectedPentagon = { name: "pentagon", edge: 5 }; 1886 | const expectedHexagon1 = { name: "hexagon", edge: 6 }; 1887 | const expectedHexagon2 = { name: "hexagon", edge: 6 }; 1888 | const expectedHexagon3 = { name: "hexagon", edge: 6 }; 1889 | const expectedHexagon4 = { name: "hexagon", edge: 6 }; 1890 | const expectedHeptagon = { name: "heptagon", edge: 7 }; 1891 | const expectedOctagon = { name: "octagon", edge: 8 }; 1892 | const expectedEnneagon = { name: "enneagon", edge: 9 }; 1893 | const expectedDecagon = { name: "decagon", edge: 10 }; 1894 | 1895 | const testArr = [ 1896 | triangle1, 1897 | triangle2, 1898 | triangle3, 1899 | square, 1900 | hexagon1, 1901 | hexagon2, 1902 | hexagon3, 1903 | hexagon4, 1904 | heptagon, 1905 | octagon, 1906 | enneagon, 1907 | decagon, 1908 | ]; 1909 | utils.insert(testArr, pentagon, polygon_cmp); 1910 | 1911 | const expectedArr = [ 1912 | expectedTriangle1, 1913 | expectedTriangle2, 1914 | expectedTriangle3, 1915 | expectedSquare, 1916 | expectedPentagon, 1917 | expectedHexagon1, 1918 | expectedHexagon2, 1919 | expectedHexagon3, 1920 | expectedHexagon4, 1921 | expectedHeptagon, 1922 | expectedOctagon, 1923 | expectedEnneagon, 1924 | expectedDecagon, 1925 | ]; 1926 | expect(testArr.length).toEqual(expectedArr.length); 1927 | for (let i = 0; i < testArr.length; ++i) { 1928 | expect(testArr[i]).toEqual(expectedArr[i]); 1929 | } 1930 | }); 1931 | 1932 | test("insertDupValToMidOfArrObjArrVal", () => { 1933 | const triangle1 = { name: "triangle", edge: 3 }; 1934 | const triangle2 = { name: "triangle", edge: 3 }; 1935 | const triangle3 = { name: "triangle", edge: 3 }; 1936 | const square = { name: "square", edge: 4 }; 1937 | const hexagon1 = { name: "hexagon", edge: 6 }; 1938 | const hexagon2 = { name: "hexagon", edge: 6 }; 1939 | const hexagon3 = { name: "hexagon", edge: 6 }; 1940 | const hexagon4 = { name: "hexagon", edge: 6 }; 1941 | const hexagon5 = { name: "hexagon", edge: 6 }; 1942 | const heptagon = { name: "heptagon", edge: 7 }; 1943 | const octagon = { name: "octagon", edge: 8 }; 1944 | const enneagon = { name: "enneagon", edge: 9 }; 1945 | const decagon = { name: "decagon", edge: 10 }; 1946 | const expectedTriangle1 = { name: "triangle", edge: 3 }; 1947 | const expectedTriangle2 = { name: "triangle", edge: 3 }; 1948 | const expectedTriangle3 = { name: "triangle", edge: 3 }; 1949 | const expectedSquare = { name: "square", edge: 4 }; 1950 | const expectedHexagon1 = { name: "hexagon", edge: 6 }; 1951 | const expectedHexagon2 = { name: "hexagon", edge: 6 }; 1952 | const expectedHexagon3 = { name: "hexagon", edge: 6 }; 1953 | const expectedHexagon4 = { name: "hexagon", edge: 6 }; 1954 | const expectedHexagon5 = { name: "hexagon", edge: 6 }; 1955 | const expectedHeptagon = { name: "heptagon", edge: 7 }; 1956 | const expectedOctagon = { name: "octagon", edge: 8 }; 1957 | const expectedEnneagon = { name: "enneagon", edge: 9 }; 1958 | const expectedDecagon = { name: "decagon", edge: 10 }; 1959 | 1960 | const testArr = [ 1961 | triangle1, 1962 | triangle2, 1963 | triangle3, 1964 | square, 1965 | hexagon1, 1966 | hexagon2, 1967 | hexagon3, 1968 | hexagon4, 1969 | heptagon, 1970 | octagon, 1971 | enneagon, 1972 | decagon, 1973 | ]; 1974 | utils.insert(testArr, hexagon5, polygon_cmp); 1975 | const expectedArr = [ 1976 | expectedTriangle1, 1977 | expectedTriangle2, 1978 | expectedTriangle3, 1979 | expectedSquare, 1980 | expectedHexagon1, 1981 | expectedHexagon2, 1982 | expectedHexagon3, 1983 | expectedHexagon4, 1984 | expectedHexagon5, 1985 | expectedHeptagon, 1986 | expectedOctagon, 1987 | expectedEnneagon, 1988 | expectedDecagon, 1989 | ]; 1990 | 1991 | expect(testArr.length).toEqual(expectedArr.length); 1992 | for (let i = 0; i < testArr.length; ++i) { 1993 | expect(testArr[i]).toEqual(expectedArr[i]); 1994 | } 1995 | }); 1996 | 1997 | test("insertToEndOfArrObjArrVal", () => { 1998 | const triangle1 = { name: "triangle", edge: 3 }; 1999 | const triangle2 = { name: "triangle", edge: 3 }; 2000 | const triangle3 = { name: "triangle", edge: 3 }; 2001 | const square = { name: "square", edge: 4 }; 2002 | const hexagon1 = { name: "hexagon", edge: 6 }; 2003 | const hexagon2 = { name: "hexagon", edge: 6 }; 2004 | const hexagon3 = { name: "hexagon", edge: 6 }; 2005 | const hexagon4 = { name: "hexagon", edge: 6 }; 2006 | const heptagon = { name: "heptagon", edge: 7 }; 2007 | const octagon = { name: "octagon", edge: 8 }; 2008 | const enneagon = { name: "enneagon", edge: 9 }; 2009 | const decagon = { name: "decagon", edge: 10 }; 2010 | const hendecagon = { name: "hendecagon", edge: 11 }; 2011 | const expectedTriangle1 = { name: "triangle", edge: 3 }; 2012 | const expectedTriangle2 = { name: "triangle", edge: 3 }; 2013 | const expectedTriangle3 = { name: "triangle", edge: 3 }; 2014 | const expectedSquare = { name: "square", edge: 4 }; 2015 | const expectedHexagon1 = { name: "hexagon", edge: 6 }; 2016 | const expectedHexagon2 = { name: "hexagon", edge: 6 }; 2017 | const expectedHexagon3 = { name: "hexagon", edge: 6 }; 2018 | const expectedHexagon4 = { name: "hexagon", edge: 6 }; 2019 | const expectedHeptagon = { name: "heptagon", edge: 7 }; 2020 | const expectedOctagon = { name: "octagon", edge: 8 }; 2021 | const expectedEnneagon = { name: "enneagon", edge: 9 }; 2022 | const expectedDecagon = { name: "decagon", edge: 10 }; 2023 | const expectedHendecagon = { name: "hendecagon", edge: 11 }; 2024 | 2025 | const testArr = [ 2026 | triangle1, 2027 | triangle2, 2028 | triangle3, 2029 | square, 2030 | hexagon1, 2031 | hexagon2, 2032 | hexagon3, 2033 | hexagon4, 2034 | heptagon, 2035 | octagon, 2036 | enneagon, 2037 | decagon, 2038 | ]; 2039 | utils.insert(testArr, hendecagon, polygon_cmp); 2040 | 2041 | const expectedArr = [ 2042 | expectedTriangle1, 2043 | expectedTriangle2, 2044 | expectedTriangle3, 2045 | expectedSquare, 2046 | expectedHexagon1, 2047 | expectedHexagon2, 2048 | expectedHexagon3, 2049 | expectedHexagon4, 2050 | expectedHeptagon, 2051 | expectedOctagon, 2052 | expectedEnneagon, 2053 | expectedDecagon, 2054 | expectedHendecagon, 2055 | ]; 2056 | 2057 | expect(testArr.length).toEqual(expectedArr.length); 2058 | for (let i = 0; i < testArr.length; ++i) { 2059 | expect(testArr[i]).toEqual(expectedArr[i]); 2060 | } 2061 | }); 2062 | 2063 | test("insertInArrNoDupVal", () => { 2064 | const testArr = [1, 2, 4, 5]; 2065 | utils.insert(testArr, 3); 2066 | const expectedArr = [1, 2, 3, 4, 5]; 2067 | expect(testArr.length).toEqual(expectedArr.length); 2068 | for (let i = 0; i < testArr.length; ++i) { 2069 | expect(testArr[i]).toEqual(expectedArr[i]); 2070 | } 2071 | }); 2072 | 2073 | test("insertEmptyArr", () => { 2074 | const testArr = []; 2075 | utils.insert(testArr, 3); 2076 | const expectedArr = [3]; 2077 | expect(testArr.length).toEqual(expectedArr.length); 2078 | for (let i = 0; i < testArr.length; ++i) { 2079 | expect(testArr[i]).toEqual(expectedArr[i]); 2080 | } 2081 | }); 2082 | 2083 | test("insertToFrontOfArr", () => { 2084 | const testArr = [1, 2, 4, 5, 6, 7, 8]; 2085 | utils.insert(testArr, 0); 2086 | 2087 | const expectedArr = [0, 1, 2, 4, 5, 6, 7, 8]; 2088 | expect(testArr.length).toEqual(expectedArr.length); 2089 | for (let i = 0; i < testArr.length; ++i) { 2090 | expect(testArr[i]).toEqual(expectedArr[i]); 2091 | } 2092 | }); 2093 | 2094 | test("insertNonDupValToMidOfArr", () => { 2095 | const testArr = [1, 1, 1, 2, 4, 4, 4, 4, 5, 6, 7, 8]; 2096 | utils.insert(testArr, 3); 2097 | 2098 | const expectedArr = [1, 1, 1, 2, 3, 4, 4, 4, 4, 5, 6, 7, 8]; 2099 | expect(testArr.length).toEqual(expectedArr.length); 2100 | for (let i = 0; i < testArr.length; ++i) { 2101 | expect(testArr[i]).toEqual(expectedArr[i]); 2102 | } 2103 | }); 2104 | 2105 | test("insertDupValToMidOfArr", () => { 2106 | const testArr = [1, 1, 1, 2, 4, 4, 4, 4, 5, 6, 7, 8]; 2107 | utils.insert(testArr, 4); 2108 | 2109 | const expectedArr = [1, 1, 1, 2, 4, 4, 4, 4, 4, 5, 6, 7, 8]; 2110 | expect(testArr.length).toEqual(expectedArr.length); 2111 | for (let i = 0; i < testArr.length; ++i) { 2112 | expect(testArr[i]).toEqual(expectedArr[i]); 2113 | } 2114 | }); 2115 | 2116 | test("insertToEndOfArr", () => { 2117 | const testArr = [1, 1, 1, 2, 4, 4, 4, 4, 5, 6, 7, 8]; 2118 | utils.insert(testArr, 9); 2119 | 2120 | const expectedArr = [1, 1, 1, 2, 4, 4, 4, 4, 5, 6, 7, 8, 9]; 2121 | expect(testArr.length).toEqual(expectedArr.length); 2122 | for (let i = 0; i < testArr.length; ++i) { 2123 | expect(testArr[i]).toEqual(expectedArr[i]); 2124 | } 2125 | }); 2126 | }); 2127 | 2128 | describe("remove", () => { 2129 | test("removeExistingValInArrNoDupValObjArrVal", () => { 2130 | const triangle = { name: "triangle", edge: 3 }; 2131 | const square = { name: "square", edge: 4 }; 2132 | const hexagon1 = { name: "hexagon", edge: 6 }; 2133 | const hexagon2 = { name: "hexagon", edge: 6 }; 2134 | const heptagon = { name: "heptagon", edge: 7 }; 2135 | const expectedTriangle = { name: "triangle", edge: 3 }; 2136 | const expectedSquare = { name: "square", edge: 4 }; 2137 | const expectedHeptagon = { name: "heptagon", edge: 7 }; 2138 | 2139 | const testArr = [triangle, square, hexagon1, heptagon]; 2140 | const success = utils.remove(testArr, hexagon2, polygon_cmp); 2141 | expect(success).toEqual(true); 2142 | 2143 | const expectedArr = [expectedTriangle, expectedSquare, expectedHeptagon]; 2144 | expect(testArr.length).toEqual(expectedArr.length); 2145 | for (let i = 0; i < testArr.length; ++i) { 2146 | expect(testArr[i]).toEqual(expectedArr[i]); 2147 | } 2148 | }); 2149 | 2150 | test("removeEmptyArrObjArrVal", () => { 2151 | const hexagon = { name: "hexagon", edge: 6 }; 2152 | 2153 | const testArr = []; 2154 | const success = utils.remove(testArr, hexagon, polygon_cmp); 2155 | expect(success).toEqual(false); 2156 | 2157 | const expectedArr = []; 2158 | expect(testArr.length).toEqual(expectedArr.length); 2159 | for (let i = 0; i < testArr.length; ++i) { 2160 | expect(testArr[i]).toEqual(expectedArr[i]); 2161 | } 2162 | }); 2163 | 2164 | test("removeExistingFirstValInArrNoDupValObjArrVal", () => { 2165 | const triangle1 = { name: "triangle", edge: 3 }; 2166 | const triangle2 = { name: "triangle", edge: 3 }; 2167 | const square = { name: "square", edge: 4 }; 2168 | const hexagon = { name: "hexagon", edge: 6 }; 2169 | const heptagon = { name: "heptagon", edge: 7 }; 2170 | const expectedTriangle = { name: "triangle", edge: 3 }; 2171 | const expectedSquare = { name: "square", edge: 4 }; 2172 | const expectedHexagon = { name: "hexagon", edge: 6 }; 2173 | const expectedHeptagon = { name: "heptagon", edge: 7 }; 2174 | 2175 | const testArr = [triangle1, square, hexagon, heptagon]; 2176 | const success = utils.remove(testArr, triangle2, polygon_cmp); 2177 | expect(success).toEqual(true); 2178 | 2179 | const expectedArr = [expectedSquare, expectedHexagon, expectedHeptagon]; 2180 | expect(testArr.length).toEqual(expectedArr.length); 2181 | for (let i = 0; i < testArr.length; ++i) { 2182 | expect(testArr[i]).toEqual(expectedArr[i]); 2183 | } 2184 | }); 2185 | 2186 | test("removeExistingTheLastValInArrNoDupValObjArrVal", () => { 2187 | const triangle = { name: "triangle", edge: 3 }; 2188 | const square = { name: "square", edge: 4 }; 2189 | const hexagon = { name: "hexagon", edge: 6 }; 2190 | const heptagon1 = { name: "heptagon", edge: 7 }; 2191 | const heptagon2 = { name: "heptagon", edge: 7 }; 2192 | const expectedTriangle = { name: "triangle", edge: 3 }; 2193 | const expectedSquare = { name: "square", edge: 4 }; 2194 | const expectedHexagon = { name: "hexagon", edge: 6 }; 2195 | 2196 | const testArr = [triangle, square, hexagon, heptagon1]; 2197 | const success = utils.remove(testArr, heptagon2, polygon_cmp); 2198 | expect(success).toEqual(true); 2199 | 2200 | const expectedArr = [expectedTriangle, expectedSquare, expectedHexagon]; 2201 | expect(testArr.length).toEqual(expectedArr.length); 2202 | for (let i = 0; i < testArr.length; ++i) { 2203 | expect(testArr[i]).toEqual(expectedArr[i]); 2204 | } 2205 | }); 2206 | 2207 | test("removeExistingDupValInArrDupValObjArrVal", () => { 2208 | const triangle = { name: "triangle", edge: 3 }; 2209 | const square = { name: "square", edge: 4 }; 2210 | const pentagon = { name: "pentagon", edge: 5 }; 2211 | const hexagon1 = { name: "hexagon", edge: 6 }; 2212 | const hexagon2 = { name: "hexagon", edge: 6 }; 2213 | const hexagon3 = { name: "hexagon", edge: 6 }; 2214 | const heptagon = { name: "heptagon", edge: 7 }; 2215 | 2216 | const expectedTriangle = { name: "triangle", edge: 3 }; 2217 | const expectedSquare = { name: "square", edge: 4 }; 2218 | const expectedHexagon = { name: "hexagon", edge: 6 }; 2219 | const expectedHeptagon = { name: "heptagon", edge: 7 }; 2220 | 2221 | const testArr = [triangle, square, hexagon1, hexagon2, heptagon]; 2222 | const success = utils.remove(testArr, hexagon3, polygon_cmp); 2223 | expect(success).toEqual(true); 2224 | 2225 | const expectedArr = [ 2226 | expectedTriangle, 2227 | expectedSquare, 2228 | expectedHexagon, 2229 | expectedHeptagon, 2230 | ]; 2231 | expect(testArr.length).toEqual(expectedArr.length); 2232 | for (let i = 0; i < testArr.length; ++i) { 2233 | expect(testArr[i]).toEqual(expectedArr[i]); 2234 | } 2235 | }); 2236 | 2237 | test("removeExistingFirstDupValInArrDupValObjArrVal", () => { 2238 | const triangle1 = { name: "triangle", edge: 3 }; 2239 | const triangle2 = { name: "triangle", edge: 3 }; 2240 | const triangle3 = { name: "triangle", edge: 3 }; 2241 | const square = { name: "square", edge: 4 }; 2242 | const hexagon = { name: "hexagon", edge: 6 }; 2243 | const heptagon = { name: "heptagon", edge: 7 }; 2244 | 2245 | const expectedTriangle = { name: "triangle", edge: 3 }; 2246 | const expectedSquare = { name: "square", edge: 4 }; 2247 | const expectedHexagon = { name: "hexagon", edge: 6 }; 2248 | const expectedHeptagon = { name: "heptagon", edge: 7 }; 2249 | 2250 | const testArr = [triangle1, triangle2, square, hexagon, heptagon]; 2251 | const success = utils.remove(testArr, triangle3, polygon_cmp); 2252 | expect(success).toEqual(true); 2253 | 2254 | const expectedArr = [ 2255 | expectedTriangle, 2256 | expectedSquare, 2257 | expectedHexagon, 2258 | expectedHeptagon, 2259 | ]; 2260 | expect(testArr.length).toEqual(expectedArr.length); 2261 | for (let i = 0; i < testArr.length; ++i) { 2262 | expect(testArr[i]).toEqual(expectedArr[i]); 2263 | } 2264 | }); 2265 | 2266 | test("removeExistingLastDupValInArrDupValObjArrVal", () => { 2267 | const triangle = { name: "triangle", edge: 3 }; 2268 | const square = { name: "square", edge: 4 }; 2269 | const hexagon = { name: "hexagon", edge: 6 }; 2270 | const heptagon1 = { name: "heptagon", edge: 7 }; 2271 | const heptagon2 = { name: "heptagon", edge: 7 }; 2272 | const heptagon3 = { name: "heptagon", edge: 7 }; 2273 | 2274 | const expectedTriangle = { name: "triangle", edge: 3 }; 2275 | const expectedSquare = { name: "square", edge: 4 }; 2276 | const expectedHexagon = { name: "hexagon", edge: 6 }; 2277 | const expectedHeptagon = { name: "heptagon", edge: 7 }; 2278 | 2279 | const testArr = [triangle, square, hexagon, heptagon1, heptagon2]; 2280 | const success = utils.remove(testArr, heptagon3, polygon_cmp); 2281 | expect(success).toEqual(true); 2282 | 2283 | const expectedArr = [ 2284 | expectedTriangle, 2285 | expectedSquare, 2286 | expectedHexagon, 2287 | expectedHeptagon, 2288 | ]; 2289 | expect(testArr.length).toEqual(expectedArr.length); 2290 | for (let i = 0; i < testArr.length; ++i) { 2291 | expect(testArr[i]).toEqual(expectedArr[i]); 2292 | } 2293 | }); 2294 | 2295 | test("removeNotExistingValInArrDupValObjArrVal", () => { 2296 | const triangle = { name: "triangle", edge: 3 }; 2297 | const square = { name: "square", edge: 4 }; 2298 | const hexagon = { name: "hexagon", edge: 6 }; 2299 | const heptagon1 = { name: "heptagon", edge: 7 }; 2300 | const heptagon2 = { name: "heptagon", edge: 7 }; 2301 | const enneagon = { name: "enneagon", edge: 9 }; 2302 | 2303 | const expectedTriangle = { name: "triangle", edge: 3 }; 2304 | const expectedSquare = { name: "square", edge: 4 }; 2305 | const expectedHexagon = { name: "hexagon", edge: 6 }; 2306 | const expectedHeptagon1 = { name: "heptagon", edge: 7 }; 2307 | const expectedHeptagon2 = { name: "heptagon", edge: 7 }; 2308 | 2309 | const testArr = [triangle, square, hexagon, heptagon1, heptagon2]; 2310 | const success = utils.remove(testArr, enneagon, polygon_cmp); 2311 | expect(success).toEqual(false); 2312 | 2313 | const expectedArr = [ 2314 | expectedTriangle, 2315 | expectedSquare, 2316 | expectedHexagon, 2317 | expectedHeptagon1, 2318 | expectedHeptagon2, 2319 | ]; 2320 | expect(testArr.length).toEqual(expectedArr.length); 2321 | for (let i = 0; i < testArr.length; ++i) { 2322 | expect(testArr[i]).toEqual(expectedArr[i]); 2323 | } 2324 | }); 2325 | 2326 | test("removeExistingValInArrNoDupVal", () => { 2327 | const testArr = [1, 2, 4, 5]; 2328 | const success = utils.remove(testArr, 4); 2329 | expect(success).toEqual(true); 2330 | 2331 | const expectedArr = [1, 2, 5]; 2332 | expect(testArr.length).toEqual(expectedArr.length); 2333 | for (let i = 0; i < testArr.length; ++i) { 2334 | expect(testArr[i]).toEqual(expectedArr[i]); 2335 | } 2336 | }); 2337 | 2338 | test("removeEmptyArr", () => { 2339 | const testArr = []; 2340 | const success = utils.remove(testArr, 4); 2341 | expect(success).toEqual(false); 2342 | 2343 | const expectedArr = []; 2344 | expect(testArr.length).toEqual(expectedArr.length); 2345 | for (let i = 0; i < testArr.length; ++i) { 2346 | expect(testArr[i]).toEqual(expectedArr[i]); 2347 | } 2348 | }); 2349 | 2350 | test("removeExistingFirstValInArrNoDupVal", () => { 2351 | const testArr = [1, 2, 4, 5]; 2352 | const success = utils.remove(testArr, 1); 2353 | expect(success).toEqual(true); 2354 | 2355 | const expectedArr = [2, 4, 5]; 2356 | expect(testArr.length).toEqual(expectedArr.length); 2357 | for (let i = 0; i < testArr.length; ++i) { 2358 | expect(testArr[i]).toEqual(expectedArr[i]); 2359 | } 2360 | }); 2361 | 2362 | test("removeExistingTheLastValInArrNoDupVal", () => { 2363 | const testArr = [1, 2, 4, 5]; 2364 | const success = utils.remove(testArr, 5); 2365 | expect(success).toEqual(true); 2366 | 2367 | const expectedArr = [1, 2, 4]; 2368 | expect(testArr.length).toEqual(expectedArr.length); 2369 | for (let i = 0; i < testArr.length; ++i) { 2370 | expect(testArr[i]).toEqual(expectedArr[i]); 2371 | } 2372 | }); 2373 | 2374 | test("removeExistingDupValInArrDupVal", () => { 2375 | const testArr = [1, 2, 4, 4, 5]; 2376 | const success = utils.remove(testArr, 4); 2377 | expect(success).toEqual(true); 2378 | 2379 | const expectedArr = [1, 2, 4, 5]; 2380 | expect(testArr.length).toEqual(expectedArr.length); 2381 | for (let i = 0; i < testArr.length; ++i) { 2382 | expect(testArr[i]).toEqual(expectedArr[i]); 2383 | } 2384 | }); 2385 | 2386 | test("removeExistingFirstDupValInArrDupVal", () => { 2387 | const testArr = [1, 1, 2, 4, 5]; 2388 | const success = utils.remove(testArr, 1); 2389 | expect(success).toEqual(true); 2390 | 2391 | const expectedArr = [1, 2, 4, 5]; 2392 | expect(testArr.length).toEqual(expectedArr.length); 2393 | for (let i = 0; i < testArr.length; ++i) { 2394 | expect(testArr[i]).toEqual(expectedArr[i]); 2395 | } 2396 | }); 2397 | 2398 | test("removeExistingLastDupValInArrDupVal", () => { 2399 | const testArr = [1, 2, 4, 5, 5]; 2400 | const success = utils.remove(testArr, 5); 2401 | expect(success).toEqual(true); 2402 | 2403 | const expectedArr = [1, 2, 4, 5]; 2404 | expect(testArr.length).toEqual(expectedArr.length); 2405 | for (let i = 0; i < testArr.length; ++i) { 2406 | expect(testArr[i]).toEqual(expectedArr[i]); 2407 | } 2408 | }); 2409 | 2410 | test("removeNotExistingValInArrDupVal", () => { 2411 | const testArr = [1, 2, 4, 5, 5]; 2412 | const success = utils.remove(testArr, 7); 2413 | expect(success).toEqual(false); 2414 | 2415 | const expectedArr = [1, 2, 4, 5, 5]; 2416 | expect(testArr.length).toEqual(expectedArr.length); 2417 | for (let i = 0; i < testArr.length; ++i) { 2418 | expect(testArr[i]).toEqual(expectedArr[i]); 2419 | } 2420 | }); 2421 | }); 2422 | 2423 | describe("binary_search", () => { 2424 | test("binary_searchExistingValNotInArrEdgeObjArrVal", () => { 2425 | const triangle = { name: "triangle", edge: 3 }; 2426 | const square = { name: "square", edge: 4 }; 2427 | const hexagon1 = { name: "hexagon", edge: 6 }; 2428 | const hexagon2 = { name: "hexagon", edge: 6 }; 2429 | const heptagon = { name: "heptagon", edge: 7 }; 2430 | 2431 | expect( 2432 | utils.binary_search( 2433 | [triangle, square, hexagon1, heptagon], 2434 | hexagon2, 2435 | polygon_cmp 2436 | ) 2437 | ).toEqual(2); 2438 | }); 2439 | 2440 | test("binary_searchEmptyArrObjArrVal", () => { 2441 | const hexagon = { name: "hexagon", edge: 6 }; 2442 | 2443 | expect(utils.binary_search([], hexagon, polygon_cmp)).toEqual(-1); 2444 | }); 2445 | 2446 | test("binary_searchExistingValAsLastElemObjArrVal", () => { 2447 | const triangle = { name: "triangle", edge: 3 }; 2448 | const square = { name: "square", edge: 4 }; 2449 | const hexagon = { name: "hexagon", edge: 6 }; 2450 | const heptagon1 = { name: "heptagon", edge: 7 }; 2451 | const heptagon2 = { name: "heptagon", edge: 7 }; 2452 | 2453 | expect( 2454 | utils.binary_search( 2455 | [triangle, square, hexagon, heptagon1], 2456 | heptagon2, 2457 | polygon_cmp 2458 | ) 2459 | ).toEqual(3); 2460 | }); 2461 | 2462 | test("binary_searchExistingValAs1stElemObjArrVal", () => { 2463 | const triangle1 = { name: "triangle", edge: 3 }; 2464 | const triangle2 = { name: "triangle", edge: 3 }; 2465 | const square = { name: "square", edge: 4 }; 2466 | const hexagon = { name: "hexagon", edge: 6 }; 2467 | const heptagon = { name: "heptagon", edge: 7 }; 2468 | 2469 | expect( 2470 | utils.binary_search( 2471 | [triangle1, square, hexagon, heptagon], 2472 | triangle2, 2473 | polygon_cmp 2474 | ) 2475 | ).toEqual(0); 2476 | }); 2477 | 2478 | test("binary_searchValSmallerThan1stElemObjArrVal", () => { 2479 | const digon = { name: "digon", edge: 2 }; 2480 | const triangle = { name: "triangle", edge: 3 }; 2481 | const square = { name: "square", edge: 4 }; 2482 | const hexagon = { name: "hexagon", edge: 6 }; 2483 | const heptagon = { name: "heptagon", edge: 7 }; 2484 | 2485 | expect( 2486 | utils.binary_search( 2487 | [triangle, square, hexagon, heptagon], 2488 | digon, 2489 | polygon_cmp 2490 | ) 2491 | ).toEqual(-1); 2492 | }); 2493 | 2494 | test("binary_searchNonExistingValInArrRangeObjArrVal", () => { 2495 | const triangle = { name: "triangle", edge: 3 }; 2496 | const square = { name: "square", edge: 4 }; 2497 | const pentagon = { name: "pentagon", edge: 5 }; 2498 | const hexagon = { name: "hexagon", edge: 6 }; 2499 | const heptagon = { name: "heptagon", edge: 7 }; 2500 | 2501 | expect( 2502 | utils.binary_search( 2503 | [triangle, square, hexagon, heptagon], 2504 | pentagon, 2505 | polygon_cmp 2506 | ) 2507 | ).toEqual(-1); 2508 | }); 2509 | 2510 | test("binary_searchValLargerThanLastElemObjArrVal", () => { 2511 | const triangle = { name: "triangle", edge: 3 }; 2512 | const square = { name: "square", edge: 4 }; 2513 | const hexagon = { name: "hexagon", edge: 6 }; 2514 | const heptagon = { name: "heptagon", edge: 7 }; 2515 | const octagon = { name: "octagon", edge: 8 }; 2516 | 2517 | expect( 2518 | utils.binary_search( 2519 | [triangle, square, hexagon, heptagon], 2520 | octagon, 2521 | polygon_cmp 2522 | ) 2523 | ).toEqual(-1); 2524 | }); 2525 | 2526 | test("binary_searchExistingDupValNotInArrEdgeObjArrVal", () => { 2527 | const triangle = { name: "triangle", edge: 3 }; 2528 | const square = { name: "square", edge: 4 }; 2529 | const hexagon1 = { name: "hexagon", edge: 6 }; 2530 | const hexagon2 = { name: "hexagon", edge: 6 }; 2531 | const hexagon3 = { name: "hexagon", edge: 6 }; 2532 | const hexagon4 = { name: "hexagon", edge: 6 }; 2533 | const heptagon = { name: "heptagon", edge: 7 }; 2534 | 2535 | const index = utils.binary_search( 2536 | [triangle, square, hexagon1, hexagon2, hexagon3, heptagon], 2537 | hexagon4, 2538 | polygon_cmp 2539 | ); 2540 | expect(index).toBeGreaterThanOrEqual(2); 2541 | expect(index).toBeLessThanOrEqual(4); 2542 | }); 2543 | 2544 | test("binary_searchExistingDupValAs1stElemObjArrVal", () => { 2545 | const triangle1 = { name: "triangle", edge: 3 }; 2546 | const triangle2 = { name: "triangle", edge: 3 }; 2547 | const triangle3 = { name: "triangle", edge: 3 }; 2548 | const triangle4 = { name: "triangle", edge: 3 }; 2549 | const square = { name: "square", edge: 4 }; 2550 | const hexagon1 = { name: "hexagon", edge: 6 }; 2551 | const hexagon2 = { name: "hexagon", edge: 6 }; 2552 | const hexagon3 = { name: "hexagon", edge: 6 }; 2553 | const heptagon = { name: "heptagon", edge: 7 }; 2554 | 2555 | const index = utils.binary_search( 2556 | [ 2557 | triangle1, 2558 | triangle2, 2559 | triangle3, 2560 | square, 2561 | hexagon1, 2562 | hexagon2, 2563 | hexagon3, 2564 | heptagon, 2565 | ], 2566 | triangle4, 2567 | polygon_cmp 2568 | ); 2569 | expect(index).toBeGreaterThanOrEqual(0); 2570 | expect(index).toBeLessThanOrEqual(2); 2571 | }); 2572 | 2573 | test("binary_searchExistingDupValAsLastElemObjArrVal", () => { 2574 | const triangle = { name: "triangle", edge: 3 }; 2575 | const square = { name: "square", edge: 4 }; 2576 | const hexagon1 = { name: "hexagon", edge: 6 }; 2577 | const hexagon2 = { name: "hexagon", edge: 6 }; 2578 | const hexagon3 = { name: "hexagon", edge: 6 }; 2579 | const heptagon1 = { name: "heptagon", edge: 7 }; 2580 | const heptagon2 = { name: "heptagon", edge: 7 }; 2581 | const heptagon3 = { name: "heptagon", edge: 7 }; 2582 | const heptagon4 = { name: "heptagon", edge: 7 }; 2583 | 2584 | const index = utils.binary_search( 2585 | [ 2586 | triangle, 2587 | square, 2588 | hexagon1, 2589 | hexagon2, 2590 | hexagon3, 2591 | heptagon1, 2592 | heptagon2, 2593 | heptagon3, 2594 | ], 2595 | heptagon4, 2596 | polygon_cmp 2597 | ); 2598 | expect(index).toBeGreaterThanOrEqual(5); 2599 | expect(index).toBeLessThanOrEqual(7); 2600 | }); 2601 | 2602 | test("binary_searchExistingValNotInArrEdge", () => { 2603 | expect(utils.binary_search([1, 2, 4, 5], 4)).toEqual(2); 2604 | }); 2605 | 2606 | test("binary_searchEmptyArr", () => { 2607 | expect(utils.binary_search([], 4)).toEqual(-1); 2608 | }); 2609 | 2610 | test("binary_searchExistingValAsLastElem", () => { 2611 | expect(utils.binary_search([1, 2, 4, 5], 5)).toEqual(3); 2612 | }); 2613 | 2614 | test("binary_searchExistingValAs1stElem", () => { 2615 | expect(utils.binary_search([1, 2, 4, 5], 1)).toEqual(0); 2616 | }); 2617 | 2618 | test("binary_searchValSmallerThan1stElem", () => { 2619 | expect(utils.binary_search([1, 2, 4, 5], 0)).toEqual(-1); 2620 | }); 2621 | 2622 | test("binary_searchNonExistingValInArrRange", () => { 2623 | expect(utils.binary_search([1, 2, 4, 5], 3)).toEqual(-1); 2624 | }); 2625 | 2626 | test("binary_searchValLargerThanLastElem", () => { 2627 | expect(utils.binary_search([1, 2, 4, 5], 6)).toEqual(-1); 2628 | }); 2629 | 2630 | test("binary_searchExistingDupValNotInArrEdge", () => { 2631 | const index = utils.binary_search([1, 2, 4, 4, 4, 5], 4); 2632 | expect(index).toBeGreaterThanOrEqual(2); 2633 | expect(index).toBeLessThanOrEqual(4); 2634 | }); 2635 | 2636 | test("binary_searchExistingDupValAs1stElem", () => { 2637 | const index = utils.binary_search([1, 1, 1, 2, 4, 4, 4, 5], 1); 2638 | expect(index).toBeGreaterThanOrEqual(0); 2639 | expect(index).toBeLessThanOrEqual(2); 2640 | }); 2641 | 2642 | test("binary_searchExistingDupValAsLastElem", () => { 2643 | const index = utils.binary_search([1, 2, 4, 4, 4, 5, 5, 5], 5); 2644 | expect(index).toBeGreaterThanOrEqual(5); 2645 | expect(index).toBeLessThanOrEqual(7); 2646 | }); 2647 | }); 2648 | 2649 | describe("binary_search_ge", () => { 2650 | test("binary_search_geExistingValNotInArrEdgeObjArrVal", () => { 2651 | const triangle = { name: "triangle", edge: 3 }; 2652 | const square = { name: "square", edge: 4 }; 2653 | const hexagon1 = { name: "hexagon", edge: 6 }; 2654 | const hexagon2 = { name: "hexagon", edge: 6 }; 2655 | const heptagon = { name: "heptagon", edge: 7 }; 2656 | 2657 | expect( 2658 | utils.binary_search_ge( 2659 | [triangle, square, hexagon1, heptagon], 2660 | hexagon2, 2661 | polygon_cmp 2662 | ) 2663 | ).toEqual(2); 2664 | }); 2665 | 2666 | test("binary_search_geEmptyArrObjArrVal", () => { 2667 | const hexagon = { name: "hexagon", edge: 6 }; 2668 | 2669 | expect(utils.binary_search_ge([], hexagon, polygon_cmp)).toEqual(0); 2670 | }); 2671 | 2672 | test("binary_search_geExistingValAsLastElemObjArrVal", () => { 2673 | const triangle = { name: "triangle", edge: 3 }; 2674 | const square = { name: "square", edge: 4 }; 2675 | const hexagon = { name: "hexagon", edge: 6 }; 2676 | const heptagon1 = { name: "heptagon", edge: 7 }; 2677 | const heptagon2 = { name: "heptagon", edge: 7 }; 2678 | 2679 | expect( 2680 | utils.binary_search_ge( 2681 | [triangle, square, hexagon, heptagon1], 2682 | heptagon2, 2683 | polygon_cmp 2684 | ) 2685 | ).toEqual(3); 2686 | }); 2687 | 2688 | test("binary_search_geExistingValAs1stElemObjArrVal", () => { 2689 | const triangle1 = { name: "triangle", edge: 3 }; 2690 | const triangle2 = { name: "triangle", edge: 3 }; 2691 | const square = { name: "square", edge: 4 }; 2692 | const hexagon = { name: "hexagon", edge: 6 }; 2693 | const heptagon = { name: "heptagon", edge: 7 }; 2694 | 2695 | expect( 2696 | utils.binary_search_ge( 2697 | [triangle1, square, hexagon, heptagon], 2698 | triangle2, 2699 | polygon_cmp 2700 | ) 2701 | ).toEqual(0); 2702 | }); 2703 | 2704 | test("binary_search_geValSmallerThan1stElemObjArrVal", () => { 2705 | const digon = { name: "digon", edge: 2 }; 2706 | const triangle = { name: "triangle", edge: 3 }; 2707 | const square = { name: "square", edge: 4 }; 2708 | const hexagon = { name: "hexagon", edge: 6 }; 2709 | const heptagon = { name: "heptagon", edge: 7 }; 2710 | 2711 | expect( 2712 | utils.binary_search_ge( 2713 | [triangle, square, hexagon, heptagon], 2714 | digon, 2715 | polygon_cmp 2716 | ) 2717 | ).toEqual(0); 2718 | }); 2719 | 2720 | test("binary_search_geNonExistingValInArrRangeObjArrVal", () => { 2721 | const triangle = { name: "triangle", edge: 3 }; 2722 | const square = { name: "square", edge: 4 }; 2723 | const pentagon = { name: "pentagon", edge: 5 }; 2724 | const hexagon = { name: "hexagon", edge: 6 }; 2725 | const heptagon = { name: "heptagon", edge: 7 }; 2726 | 2727 | expect( 2728 | utils.binary_search_ge( 2729 | [triangle, square, hexagon, heptagon], 2730 | pentagon, 2731 | polygon_cmp 2732 | ) 2733 | ).toEqual(2); 2734 | }); 2735 | 2736 | test("binary_search_geValLargerThanLastElemObjArrVal", () => { 2737 | const triangle = { name: "triangle", edge: 3 }; 2738 | const square = { name: "square", edge: 4 }; 2739 | const hexagon = { name: "hexagon", edge: 6 }; 2740 | const heptagon = { name: "heptagon", edge: 7 }; 2741 | const octagon = { name: "octagon", edge: 8 }; 2742 | 2743 | expect( 2744 | utils.binary_search_ge( 2745 | [triangle, square, hexagon, heptagon], 2746 | octagon, 2747 | polygon_cmp 2748 | ) 2749 | ).toEqual(4); 2750 | }); 2751 | 2752 | test("binary_search_geExistingDupValNotInArrEdgeObjArrVal", () => { 2753 | const triangle = { name: "triangle", edge: 3 }; 2754 | const square = { name: "square", edge: 4 }; 2755 | const hexagon1 = { name: "hexagon", edge: 6 }; 2756 | const hexagon2 = { name: "hexagon", edge: 6 }; 2757 | const hexagon3 = { name: "hexagon", edge: 6 }; 2758 | const hexagon4 = { name: "hexagon", edge: 6 }; 2759 | const heptagon = { name: "heptagon", edge: 7 }; 2760 | 2761 | expect( 2762 | utils.binary_search_ge( 2763 | [triangle, square, hexagon1, hexagon2, hexagon3, heptagon], 2764 | hexagon4, 2765 | polygon_cmp 2766 | ) 2767 | ).toEqual(2); 2768 | }); 2769 | 2770 | test("binary_search_geExistingDupValAs1stElemObjArrVal", () => { 2771 | const triangle1 = { name: "triangle", edge: 3 }; 2772 | const triangle2 = { name: "triangle", edge: 3 }; 2773 | const triangle3 = { name: "triangle", edge: 3 }; 2774 | const triangle4 = { name: "triangle", edge: 3 }; 2775 | const square = { name: "square", edge: 4 }; 2776 | const hexagon1 = { name: "hexagon", edge: 6 }; 2777 | const hexagon2 = { name: "hexagon", edge: 6 }; 2778 | const hexagon3 = { name: "hexagon", edge: 6 }; 2779 | const heptagon = { name: "heptagon", edge: 7 }; 2780 | 2781 | expect( 2782 | utils.binary_search_ge( 2783 | [ 2784 | triangle1, 2785 | triangle2, 2786 | triangle3, 2787 | square, 2788 | hexagon1, 2789 | hexagon2, 2790 | hexagon3, 2791 | heptagon, 2792 | ], 2793 | triangle4, 2794 | polygon_cmp 2795 | ) 2796 | ).toEqual(0); 2797 | }); 2798 | 2799 | test("binary_search_geExistingDupValAsLastElemObjArrVal", () => { 2800 | const triangle = { name: "triangle", edge: 3 }; 2801 | const square = { name: "square", edge: 4 }; 2802 | const hexagon1 = { name: "hexagon", edge: 6 }; 2803 | const hexagon2 = { name: "hexagon", edge: 6 }; 2804 | const hexagon3 = { name: "hexagon", edge: 6 }; 2805 | const heptagon1 = { name: "heptagon", edge: 7 }; 2806 | const heptagon2 = { name: "heptagon", edge: 7 }; 2807 | const heptagon3 = { name: "heptagon", edge: 7 }; 2808 | const heptagon4 = { name: "heptagon", edge: 7 }; 2809 | 2810 | expect( 2811 | utils.binary_search_ge( 2812 | [ 2813 | triangle, 2814 | square, 2815 | hexagon1, 2816 | hexagon2, 2817 | hexagon3, 2818 | heptagon1, 2819 | heptagon2, 2820 | heptagon3, 2821 | ], 2822 | heptagon4, 2823 | polygon_cmp 2824 | ) 2825 | ).toEqual(5); 2826 | }); 2827 | 2828 | test("binary_search_geExistingValNotInArrEdge", () => { 2829 | expect(utils.binary_search_ge([1, 2, 4, 5], 4)).toEqual(2); 2830 | }); 2831 | 2832 | test("binary_search_geEmptyArr", () => { 2833 | expect(utils.binary_search_ge([], 4)).toEqual(0); 2834 | }); 2835 | 2836 | test("binary_search_geExistingValAsLastElem", () => { 2837 | expect(utils.binary_search_ge([1, 2, 4, 5], 5)).toEqual(3); 2838 | }); 2839 | 2840 | test("binary_search_geExistingValAs1stElem", () => { 2841 | expect(utils.binary_search_ge([1, 2, 4, 5], 1)).toEqual(0); 2842 | }); 2843 | 2844 | test("binary_search_geValSmallerThan1stElem", () => { 2845 | expect(utils.binary_search_ge([1, 2, 4, 5], 0)).toEqual(0); 2846 | }); 2847 | 2848 | test("binary_search_geNonExistingValInArrRange", () => { 2849 | expect(utils.binary_search_ge([1, 2, 4, 5], 3)).toEqual(2); 2850 | }); 2851 | 2852 | test("binary_search_geValLargerThanLastElem", () => { 2853 | expect(utils.binary_search_ge([1, 2, 4, 5], 6)).toEqual(4); 2854 | }); 2855 | 2856 | test("binary_search_geExistingDupValNotInArrEdge", () => { 2857 | expect(utils.binary_search_ge([1, 2, 4, 4, 4, 5], 4)).toEqual(2); 2858 | }); 2859 | 2860 | test("binary_search_geExistingDupValAs1stElem", () => { 2861 | expect(utils.binary_search_ge([1, 1, 1, 2, 4, 4, 4, 5], 1)).toEqual(0); 2862 | }); 2863 | 2864 | test("binary_search_geExistingDupValAsLastElem", () => { 2865 | expect(utils.binary_search_ge([1, 2, 4, 4, 4, 5, 5, 5], 5)).toEqual(5); 2866 | }); 2867 | }); 2868 | 2869 | describe("binary_search_gt", () => { 2870 | test("binary_search_gtExistingValNotInArrEdgeObjArrVal", () => { 2871 | const triangle = { name: "triangle", edge: 3 }; 2872 | const square = { name: "square", edge: 4 }; 2873 | const hexagon1 = { name: "hexagon", edge: 6 }; 2874 | const hexagon2 = { name: "hexagon", edge: 6 }; 2875 | const heptagon = { name: "heptagon", edge: 7 }; 2876 | 2877 | expect( 2878 | utils.binary_search_gt( 2879 | [triangle, square, hexagon1, heptagon], 2880 | hexagon2, 2881 | polygon_cmp 2882 | ) 2883 | ).toEqual(3); 2884 | }); 2885 | 2886 | test("binary_search_gtEmptyArrObjArrVal", () => { 2887 | const hexagon = { name: "hexagon", edge: 6 }; 2888 | 2889 | expect(utils.binary_search_gt([], hexagon, polygon_cmp)).toEqual(0); 2890 | }); 2891 | 2892 | test("binary_search_gtExistingValAsLastElemObjArrVal", () => { 2893 | const triangle = { name: "triangle", edge: 3 }; 2894 | const square = { name: "square", edge: 4 }; 2895 | const hexagon = { name: "hexagon", edge: 6 }; 2896 | const heptagon1 = { name: "heptagon", edge: 7 }; 2897 | const heptagon2 = { name: "heptagon", edge: 7 }; 2898 | 2899 | expect( 2900 | utils.binary_search_gt( 2901 | [triangle, square, hexagon, heptagon1], 2902 | heptagon2, 2903 | polygon_cmp 2904 | ) 2905 | ).toEqual(4); 2906 | }); 2907 | 2908 | test("binary_search_gtExistingValAs1stElemObjArrVal", () => { 2909 | const triangle1 = { name: "triangle", edge: 3 }; 2910 | const triangle2 = { name: "triangle", edge: 3 }; 2911 | const square = { name: "square", edge: 4 }; 2912 | const hexagon = { name: "hexagon", edge: 6 }; 2913 | const heptagon = { name: "heptagon", edge: 7 }; 2914 | 2915 | expect( 2916 | utils.binary_search_gt( 2917 | [triangle1, square, hexagon, heptagon], 2918 | triangle2, 2919 | polygon_cmp 2920 | ) 2921 | ).toEqual(1); 2922 | }); 2923 | 2924 | test("binary_search_gtValSmallerThan1stElemObjArrVal", () => { 2925 | const digon = { name: "digon", edge: 2 }; 2926 | const triangle = { name: "triangle", edge: 3 }; 2927 | const square = { name: "square", edge: 4 }; 2928 | const hexagon = { name: "hexagon", edge: 6 }; 2929 | const heptagon = { name: "heptagon", edge: 7 }; 2930 | 2931 | expect( 2932 | utils.binary_search_gt( 2933 | [triangle, square, hexagon, heptagon], 2934 | digon, 2935 | polygon_cmp 2936 | ) 2937 | ).toEqual(0); 2938 | }); 2939 | 2940 | test("binary_search_gtNonExistingValInArrRangeObjArrVal", () => { 2941 | const triangle = { name: "triangle", edge: 3 }; 2942 | const square = { name: "square", edge: 4 }; 2943 | const pentagon = { name: "pentagon", edge: 5 }; 2944 | const hexagon = { name: "hexagon", edge: 6 }; 2945 | const heptagon = { name: "heptagon", edge: 7 }; 2946 | 2947 | expect( 2948 | utils.binary_search_gt( 2949 | [triangle, square, hexagon, heptagon], 2950 | pentagon, 2951 | polygon_cmp 2952 | ) 2953 | ).toEqual(2); 2954 | }); 2955 | 2956 | test("binary_search_gtValLargerThanLastElemObjArrVal", () => { 2957 | const triangle = { name: "triangle", edge: 3 }; 2958 | const square = { name: "square", edge: 4 }; 2959 | const hexagon = { name: "hexagon", edge: 6 }; 2960 | const heptagon = { name: "heptagon", edge: 7 }; 2961 | const octagon = { name: "octagon", edge: 8 }; 2962 | 2963 | expect( 2964 | utils.binary_search_gt( 2965 | [triangle, square, hexagon, heptagon], 2966 | octagon, 2967 | polygon_cmp 2968 | ) 2969 | ).toEqual(4); 2970 | }); 2971 | 2972 | test("binary_search_gtExistingDupValNotInArrEdgeObjArrVal", () => { 2973 | const triangle = { name: "triangle", edge: 3 }; 2974 | const square = { name: "square", edge: 4 }; 2975 | const hexagon1 = { name: "hexagon", edge: 6 }; 2976 | const hexagon2 = { name: "hexagon", edge: 6 }; 2977 | const hexagon3 = { name: "hexagon", edge: 6 }; 2978 | const hexagon4 = { name: "hexagon", edge: 6 }; 2979 | const heptagon = { name: "heptagon", edge: 7 }; 2980 | 2981 | expect( 2982 | utils.binary_search_gt( 2983 | [triangle, square, hexagon1, hexagon2, hexagon3, heptagon], 2984 | hexagon4, 2985 | polygon_cmp 2986 | ) 2987 | ).toEqual(5); 2988 | }); 2989 | 2990 | test("binary_search_gtExistingDupValAs1stElemObjArrVal", () => { 2991 | const triangle1 = { name: "triangle", edge: 3 }; 2992 | const triangle2 = { name: "triangle", edge: 3 }; 2993 | const triangle3 = { name: "triangle", edge: 3 }; 2994 | const triangle4 = { name: "triangle", edge: 3 }; 2995 | const square = { name: "square", edge: 4 }; 2996 | const hexagon1 = { name: "hexagon", edge: 6 }; 2997 | const hexagon2 = { name: "hexagon", edge: 6 }; 2998 | const hexagon3 = { name: "hexagon", edge: 6 }; 2999 | const heptagon = { name: "heptagon", edge: 7 }; 3000 | 3001 | expect( 3002 | utils.binary_search_gt( 3003 | [ 3004 | triangle1, 3005 | triangle2, 3006 | triangle3, 3007 | square, 3008 | hexagon1, 3009 | hexagon2, 3010 | hexagon3, 3011 | heptagon, 3012 | ], 3013 | triangle4, 3014 | polygon_cmp 3015 | ) 3016 | ).toEqual(3); 3017 | }); 3018 | 3019 | test("binary_search_gtExistingDupValAsLastElemObjArrVal", () => { 3020 | const triangle = { name: "triangle", edge: 3 }; 3021 | const square = { name: "square", edge: 4 }; 3022 | const hexagon1 = { name: "hexagon", edge: 6 }; 3023 | const hexagon2 = { name: "hexagon", edge: 6 }; 3024 | const hexagon3 = { name: "hexagon", edge: 6 }; 3025 | const heptagon1 = { name: "heptagon", edge: 7 }; 3026 | const heptagon2 = { name: "heptagon", edge: 7 }; 3027 | const heptagon3 = { name: "heptagon", edge: 7 }; 3028 | const heptagon4 = { name: "heptagon", edge: 7 }; 3029 | 3030 | expect( 3031 | utils.binary_search_gt( 3032 | [ 3033 | triangle, 3034 | square, 3035 | hexagon1, 3036 | hexagon2, 3037 | hexagon3, 3038 | heptagon1, 3039 | heptagon2, 3040 | heptagon3, 3041 | ], 3042 | heptagon4, 3043 | polygon_cmp 3044 | ) 3045 | ).toEqual(8); 3046 | }); 3047 | 3048 | test("binary_search_gtExistingValNotInArrEdge", () => { 3049 | expect(utils.binary_search_gt([1, 2, 4, 5], 4)).toEqual(3); 3050 | }); 3051 | 3052 | test("binary_search_gtEmptyArr", () => { 3053 | expect(utils.binary_search_gt([], 4)).toEqual(0); 3054 | }); 3055 | 3056 | test("binary_search_gtExistingValAsLastElem", () => { 3057 | expect(utils.binary_search_gt([1, 2, 4, 5], 5)).toEqual(4); 3058 | }); 3059 | 3060 | test("binary_search_gtExistingValAs1stElem", () => { 3061 | expect(utils.binary_search_gt([1, 2, 4, 5], 1)).toEqual(1); 3062 | }); 3063 | 3064 | test("binary_search_gtValSmallerThan1stElem", () => { 3065 | expect(utils.binary_search_gt([1, 2, 4, 5], 0)).toEqual(0); 3066 | }); 3067 | 3068 | test("binary_search_gtNonExistingValInArrRange", () => { 3069 | expect(utils.binary_search_gt([1, 2, 4, 5], 3)).toEqual(2); 3070 | }); 3071 | 3072 | test("binary_search_gtValLargerThanLastElem", () => { 3073 | expect(utils.binary_search_gt([1, 2, 4, 5], 6)).toEqual(4); 3074 | }); 3075 | 3076 | test("binary_search_gtExistingDupValNotInArrEdge", () => { 3077 | expect(utils.binary_search_gt([1, 2, 4, 4, 4, 5], 4)).toEqual(5); 3078 | }); 3079 | 3080 | test("binary_search_gtExistingDupValAs1stElem", () => { 3081 | expect(utils.binary_search_gt([1, 1, 1, 2, 4, 4, 4, 5], 1)).toEqual(3); 3082 | }); 3083 | 3084 | test("binary_search_gtExistingDupValAsLastElem", () => { 3085 | expect(utils.binary_search_gt([1, 2, 4, 4, 4, 5, 5, 5], 5)).toEqual(8); 3086 | }); 3087 | }); 3088 | 3089 | describe("equal_range", () => { 3090 | test("equal_rangeExistingValNotInArrEdgeObjArrVal", () => { 3091 | const triangle = { name: "triangle", edge: 3 }; 3092 | const square = { name: "square", edge: 4 }; 3093 | const hexagon1 = { name: "hexagon", edge: 6 }; 3094 | const hexagon2 = { name: "hexagon", edge: 6 }; 3095 | const heptagon = { name: "heptagon", edge: 7 }; 3096 | 3097 | const testArr = utils.equal_range( 3098 | [triangle, square, hexagon1, heptagon], 3099 | hexagon2, 3100 | polygon_cmp 3101 | ); 3102 | const expectedArr = [2, 3]; 3103 | expect(testArr.length).toEqual(expectedArr.length); 3104 | for (let i = 0; i < testArr.length; ++i) { 3105 | expect(testArr[i]).toEqual(expectedArr[i]); 3106 | } 3107 | }); 3108 | 3109 | test("equal_rangeEmptyArrObjArrVal", () => { 3110 | const hexagon = { name: "hexagon", edge: 6 }; 3111 | 3112 | const testArr = utils.equal_range([], hexagon, polygon_cmp); 3113 | const expectedArr = [0, 0]; 3114 | expect(testArr.length).toEqual(expectedArr.length); 3115 | for (let i = 0; i < testArr.length; ++i) { 3116 | expect(testArr[i]).toEqual(expectedArr[i]); 3117 | } 3118 | }); 3119 | 3120 | test("equal_rangeExistingValAs1stElemObjArrVal", () => { 3121 | const triangle1 = { name: "triangle", edge: 3 }; 3122 | const triangle2 = { name: "triangle", edge: 3 }; 3123 | const square = { name: "square", edge: 4 }; 3124 | const hexagon = { name: "hexagon", edge: 6 }; 3125 | const heptagon = { name: "heptagon", edge: 7 }; 3126 | 3127 | const testArr = utils.equal_range( 3128 | [triangle1, square, hexagon, heptagon], 3129 | triangle2, 3130 | polygon_cmp 3131 | ); 3132 | const expectedArr = [0, 1]; 3133 | expect(testArr.length).toEqual(expectedArr.length); 3134 | for (let i = 0; i < testArr.length; ++i) { 3135 | expect(testArr[i]).toEqual(expectedArr[i]); 3136 | } 3137 | }); 3138 | 3139 | test("equal_rangeExistingValAsLastElemObjArrVal", () => { 3140 | const triangle = { name: "triangle", edge: 3 }; 3141 | const square = { name: "square", edge: 4 }; 3142 | const hexagon = { name: "hexagon", edge: 6 }; 3143 | const heptagon1 = { name: "heptagon", edge: 7 }; 3144 | const heptagon2 = { name: "heptagon", edge: 7 }; 3145 | 3146 | const testArr = utils.equal_range( 3147 | [triangle, square, hexagon, heptagon1], 3148 | heptagon2, 3149 | polygon_cmp 3150 | ); 3151 | const expectedArr = [3, 4]; 3152 | expect(testArr.length).toEqual(expectedArr.length); 3153 | for (let i = 0; i < testArr.length; ++i) { 3154 | expect(testArr[i]).toEqual(expectedArr[i]); 3155 | } 3156 | }); 3157 | 3158 | test("equal_rangeExistingDupValAs1stElemObjArrVal", () => { 3159 | const triangle1 = { name: "triangle", edge: 3 }; 3160 | const triangle2 = { name: "triangle", edge: 3 }; 3161 | const triangle3 = { name: "triangle", edge: 3 }; 3162 | const triangle4 = { name: "triangle", edge: 3 }; 3163 | const square = { name: "square", edge: 4 }; 3164 | const hexagon = { name: "hexagon", edge: 6 }; 3165 | const heptagon = { name: "heptagon", edge: 7 }; 3166 | 3167 | const testArr = utils.equal_range( 3168 | [triangle1, triangle2, triangle3, square, hexagon, heptagon], 3169 | triangle4, 3170 | polygon_cmp 3171 | ); 3172 | const expectedArr = [0, 3]; 3173 | expect(testArr.length).toEqual(expectedArr.length); 3174 | for (let i = 0; i < testArr.length; ++i) { 3175 | expect(testArr[i]).toEqual(expectedArr[i]); 3176 | } 3177 | }); 3178 | 3179 | test("equal_rangeExistingDupValNotInArrEdgeObjArrVal", () => { 3180 | const triangle1 = { name: "triangle", edge: 3 }; 3181 | const triangle2 = { name: "triangle", edge: 3 }; 3182 | const triangle3 = { name: "triangle", edge: 3 }; 3183 | const square1 = { name: "square", edge: 4 }; 3184 | const square2 = { name: "square", edge: 4 }; 3185 | const square3 = { name: "square", edge: 4 }; 3186 | const square4 = { name: "square", edge: 4 }; 3187 | const hexagon = { name: "hexagon", edge: 6 }; 3188 | const heptagon = { name: "heptagon", edge: 7 }; 3189 | 3190 | const testArr = utils.equal_range( 3191 | [ 3192 | triangle1, 3193 | triangle2, 3194 | triangle3, 3195 | square1, 3196 | square2, 3197 | square3, 3198 | hexagon, 3199 | heptagon, 3200 | ], 3201 | square4, 3202 | polygon_cmp 3203 | ); 3204 | const expectedArr = [3, 6]; 3205 | expect(testArr.length).toEqual(expectedArr.length); 3206 | for (let i = 0; i < testArr.length; ++i) { 3207 | expect(testArr[i]).toEqual(expectedArr[i]); 3208 | } 3209 | }); 3210 | 3211 | test("equal_rangeExistingDupValAsLastElemObjArrVal", () => { 3212 | const triangle1 = { name: "triangle", edge: 3 }; 3213 | const triangle2 = { name: "triangle", edge: 3 }; 3214 | const triangle3 = { name: "triangle", edge: 3 }; 3215 | const square1 = { name: "square", edge: 4 }; 3216 | const square2 = { name: "square", edge: 4 }; 3217 | const square3 = { name: "square", edge: 4 }; 3218 | const hexagon = { name: "hexagon", edge: 6 }; 3219 | const heptagon1 = { name: "heptagon", edge: 7 }; 3220 | const heptagon2 = { name: "heptagon", edge: 7 }; 3221 | const heptagon3 = { name: "heptagon", edge: 7 }; 3222 | 3223 | const testArr = utils.equal_range( 3224 | [ 3225 | triangle1, 3226 | triangle2, 3227 | triangle3, 3228 | square1, 3229 | square2, 3230 | square3, 3231 | hexagon, 3232 | heptagon1, 3233 | heptagon2, 3234 | ], 3235 | heptagon3, 3236 | polygon_cmp 3237 | ); 3238 | const expectedArr = [7, 9]; 3239 | expect(testArr.length).toEqual(expectedArr.length); 3240 | for (let i = 0; i < testArr.length; ++i) { 3241 | expect(testArr[i]).toEqual(expectedArr[i]); 3242 | } 3243 | }); 3244 | 3245 | test("equal_rangeValSmallerThan1stElemObjArrVal", () => { 3246 | const digon = { name: "digon", edge: 2 }; 3247 | const triangle1 = { name: "triangle", edge: 3 }; 3248 | const triangle2 = { name: "triangle", edge: 3 }; 3249 | const triangle3 = { name: "triangle", edge: 3 }; 3250 | const square1 = { name: "square", edge: 4 }; 3251 | const square2 = { name: "square", edge: 4 }; 3252 | const square3 = { name: "square", edge: 4 }; 3253 | const hexagon = { name: "hexagon", edge: 6 }; 3254 | const heptagon1 = { name: "heptagon", edge: 7 }; 3255 | const heptagon2 = { name: "heptagon", edge: 7 }; 3256 | 3257 | const testArr = utils.equal_range( 3258 | [ 3259 | triangle1, 3260 | triangle2, 3261 | triangle3, 3262 | square1, 3263 | square2, 3264 | square3, 3265 | hexagon, 3266 | heptagon1, 3267 | heptagon2, 3268 | ], 3269 | digon, 3270 | polygon_cmp 3271 | ); 3272 | const expectedArr = [0, 0]; 3273 | expect(testArr.length).toEqual(expectedArr.length); 3274 | for (let i = 0; i < testArr.length; ++i) { 3275 | expect(testArr[i]).toEqual(expectedArr[i]); 3276 | } 3277 | }); 3278 | 3279 | test("equal_rangeNonExistingValInArrRangeObjArrVal", () => { 3280 | const triangle1 = { name: "triangle", edge: 3 }; 3281 | const triangle2 = { name: "triangle", edge: 3 }; 3282 | const triangle3 = { name: "triangle", edge: 3 }; 3283 | const square1 = { name: "square", edge: 4 }; 3284 | const square2 = { name: "square", edge: 4 }; 3285 | const square3 = { name: "square", edge: 4 }; 3286 | const pentagon = { name: "pentagon", edge: 5 }; 3287 | const hexagon = { name: "hexagon", edge: 6 }; 3288 | const heptagon1 = { name: "heptagon", edge: 7 }; 3289 | const heptagon2 = { name: "heptagon", edge: 7 }; 3290 | 3291 | const testArr = utils.equal_range( 3292 | [ 3293 | triangle1, 3294 | triangle2, 3295 | triangle3, 3296 | square1, 3297 | square2, 3298 | square3, 3299 | hexagon, 3300 | heptagon1, 3301 | heptagon2, 3302 | ], 3303 | pentagon, 3304 | polygon_cmp 3305 | ); 3306 | 3307 | const expectedArr = [6, 6]; 3308 | expect(testArr.length).toEqual(expectedArr.length); 3309 | for (let i = 0; i < testArr.length; ++i) { 3310 | expect(testArr[i]).toEqual(expectedArr[i]); 3311 | } 3312 | }); 3313 | 3314 | test("equal_rangeValLargerThanLastElemObjArrVal", () => { 3315 | const triangle1 = { name: "triangle", edge: 3 }; 3316 | const triangle2 = { name: "triangle", edge: 3 }; 3317 | const triangle3 = { name: "triangle", edge: 3 }; 3318 | const square1 = { name: "square", edge: 4 }; 3319 | const square2 = { name: "square", edge: 4 }; 3320 | const square3 = { name: "square", edge: 4 }; 3321 | const hexagon = { name: "hexagon", edge: 6 }; 3322 | const heptagon1 = { name: "heptagon", edge: 7 }; 3323 | const heptagon2 = { name: "heptagon", edge: 7 }; 3324 | let triacontakaipentagon = { name: "triacontakaipentagon", edge: 35 }; 3325 | 3326 | const testArr = utils.equal_range( 3327 | [ 3328 | triangle1, 3329 | triangle2, 3330 | triangle3, 3331 | square1, 3332 | square2, 3333 | square3, 3334 | hexagon, 3335 | heptagon1, 3336 | heptagon2, 3337 | ], 3338 | triacontakaipentagon, 3339 | polygon_cmp 3340 | ); 3341 | 3342 | const expectedArr = [9, 9]; 3343 | expect(testArr.length).toEqual(expectedArr.length); 3344 | for (let i = 0; i < testArr.length; ++i) { 3345 | expect(testArr[i]).toEqual(expectedArr[i]); 3346 | } 3347 | }); 3348 | 3349 | test("equal_rangeExistingValNotInArrEdge", () => { 3350 | const testArr = utils.equal_range([1, 2, 4, 5], 4); 3351 | const expectedArr = [2, 3]; 3352 | expect(testArr.length).toEqual(expectedArr.length); 3353 | for (let i = 0; i < testArr.length; ++i) { 3354 | expect(testArr[i]).toEqual(expectedArr[i]); 3355 | } 3356 | }); 3357 | 3358 | test("equal_rangeEmptyArr", () => { 3359 | const testArr = utils.equal_range([], 4); 3360 | const expectedArr = [0, 0]; 3361 | expect(testArr.length).toEqual(expectedArr.length); 3362 | for (let i = 0; i < testArr.length; ++i) { 3363 | expect(testArr[i]).toEqual(expectedArr[i]); 3364 | } 3365 | }); 3366 | 3367 | test("equal_rangeExistingValAs1stElem", () => { 3368 | const testArr = utils.equal_range([1, 2, 4, 5], 1); 3369 | const expectedArr = [0, 1]; 3370 | expect(testArr.length).toEqual(expectedArr.length); 3371 | for (let i = 0; i < testArr.length; ++i) { 3372 | expect(testArr[i]).toEqual(expectedArr[i]); 3373 | } 3374 | }); 3375 | 3376 | test("equal_rangeExistingValAsLastElem", () => { 3377 | const testArr = utils.equal_range([1, 2, 4, 5], 5); 3378 | const expectedArr = [3, 4]; 3379 | expect(testArr.length).toEqual(expectedArr.length); 3380 | for (let i = 0; i < testArr.length; ++i) { 3381 | expect(testArr[i]).toEqual(expectedArr[i]); 3382 | } 3383 | }); 3384 | 3385 | test("equal_rangeExistingDupValAs1stElem", () => { 3386 | const testArr = utils.equal_range([1, 1, 1, 2, 4, 5], 1); 3387 | const expectedArr = [0, 3]; 3388 | expect(testArr.length).toEqual(expectedArr.length); 3389 | for (let i = 0; i < testArr.length; ++i) { 3390 | expect(testArr[i]).toEqual(expectedArr[i]); 3391 | } 3392 | }); 3393 | 3394 | test("equal_rangeExistingDupValNotInArrEdge", () => { 3395 | const testArr = utils.equal_range([1, 1, 1, 2, 2, 2, 4, 5], 2); 3396 | const expectedArr = [3, 6]; 3397 | expect(testArr.length).toEqual(expectedArr.length); 3398 | for (let i = 0; i < testArr.length; ++i) { 3399 | expect(testArr[i]).toEqual(expectedArr[i]); 3400 | } 3401 | }); 3402 | 3403 | test("equal_rangeExistingDupValAsLastElem", () => { 3404 | const testArr = utils.equal_range([1, 1, 1, 2, 2, 2, 4, 5, 5], 5); 3405 | const expectedArr = [7, 9]; 3406 | expect(testArr.length).toEqual(expectedArr.length); 3407 | for (let i = 0; i < testArr.length; ++i) { 3408 | expect(testArr[i]).toEqual(expectedArr[i]); 3409 | } 3410 | }); 3411 | 3412 | test("equal_rangeValSmallerThan1stElem", () => { 3413 | const testArr = utils.equal_range([1, 1, 1, 2, 2, 2, 4, 5, 5], 0); 3414 | const expectedArr = [0, 0]; 3415 | expect(testArr.length).toEqual(expectedArr.length); 3416 | for (let i = 0; i < testArr.length; ++i) { 3417 | expect(testArr[i]).toEqual(expectedArr[i]); 3418 | } 3419 | }); 3420 | 3421 | test("equal_rangeNonExistingValInArrRange", () => { 3422 | const testArr = utils.equal_range([1, 1, 1, 2, 2, 2, 4, 5, 5], 3); 3423 | const expectedArr = [6, 6]; 3424 | expect(testArr.length).toEqual(expectedArr.length); 3425 | for (let i = 0; i < testArr.length; ++i) { 3426 | expect(testArr[i]).toEqual(expectedArr[i]); 3427 | } 3428 | }); 3429 | 3430 | test("equal_rangeValLargerThanLastElem", () => { 3431 | const testArr = utils.equal_range([1, 1, 1, 2, 2, 2, 4, 5, 5], 33); 3432 | const expectedArr = [9, 9]; 3433 | expect(testArr.length).toEqual(expectedArr.length); 3434 | for (let i = 0; i < testArr.length; ++i) { 3435 | expect(testArr[i]).toEqual(expectedArr[i]); 3436 | } 3437 | }); 3438 | }); 3439 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license Apache-2.0 3 | * 4 | * Copyright (c) 2021 Patrick Chan 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | /** 20 | * The type of the optional comparation function used in many of the module functions. 21 | */ 22 | // JSDoc not supporting to parse the following type yet. 23 | // https://github.com/jsdoctypeparser/jsdoctypeparser/issues/50 24 | type cmpFn = (elem1: T, elem2: T) => number; 25 | 26 | /** 27 | * Returns a negative number, zero, or a positive number depending on whether the 28 | * first argument is less than, equal to, or greater than the second argument. 29 | * The default comparation function if the optional comparation function is not offered. 30 | * @param {T} elem1 The first element. 31 | * @param {T} elem2 The second element. 32 | * @return {number} 33 | */ 34 | function defaultCmp(elem1: T, elem2: T): number { 35 | return elem1 > elem2 ? 1 : elem1 < elem2 ? -1 : 0; 36 | } 37 | 38 | /** 39 | * Returns the array after the doing union operation to two arrays. 40 | * @param {Array} arr1 The first array. 41 | * @param {Array} arr2 The second array. 42 | * @param {?function(T,T):number=} opt_cmpFn Optional comparison 43 | * function by which the array is to be ordered. It should take 2 arguments to 44 | * compare, and it returns a negative number, zero, or a positive number depending on 45 | * whether the first argument is less than, equal to, or greater than the second argument. 46 | * @return {T[]} The array after the union operation. 47 | */ 48 | function union(arr1: T[], arr2: T[], opt_cmpFn: cmpFn = null): T[] { 49 | const cmp = opt_cmpFn || defaultCmp; 50 | const retval = []; 51 | 52 | let j = 0; 53 | let k = 0; 54 | 55 | while (j < arr1.length && k < arr2.length) { 56 | if (cmp(arr1[j], arr2[k]) === 0) { 57 | retval.push(arr1[j]); 58 | j++; 59 | k++; 60 | } else { 61 | if (cmp(arr1[j], arr2[k]) < 0) { 62 | retval.push(arr1[j]); 63 | j++; 64 | } else { 65 | retval.push(arr2[k]); 66 | k++; 67 | } 68 | } 69 | } 70 | 71 | if (j === arr1.length) { 72 | for (let i = k; i < arr2.length; ++i) { 73 | retval.push(arr2[i]); 74 | } 75 | } else { 76 | for (let i = j; i < arr1.length; ++i) { 77 | retval.push(arr1[i]); 78 | } 79 | } 80 | 81 | return retval; 82 | } 83 | 84 | /** 85 | * Returns the array after the doing intersection operation to two arrays. 86 | * @param {Array} arr1 The first array. 87 | * @param {Array} arr2 The second array. 88 | * @param {?function(T,T):number=} opt_cmpFn Optional comparison 89 | * function by which the array is to be ordered. It should take 2 arguments to 90 | * compare, and it returns a negative number, zero, or a positive number depending on 91 | * whether the first argument is less than, equal to, or greater than the second argument. 92 | * @return {T[]} The array after the intersection operation. 93 | */ 94 | function intersection( 95 | arr1: T[], 96 | arr2: T[], 97 | opt_cmpFn: cmpFn = null 98 | ): T[] { 99 | const cmp = opt_cmpFn || defaultCmp; 100 | const retval = []; 101 | 102 | let j = 0; 103 | let k = 0; 104 | 105 | while (j < arr1.length && k < arr2.length) { 106 | if (cmp(arr1[j], arr2[k]) === 0) { 107 | retval.push(arr1[j]); 108 | j++; 109 | k++; 110 | } else { 111 | if (cmp(arr1[j], arr2[k]) < 0) { 112 | j++; 113 | } else { 114 | k++; 115 | } 116 | } 117 | } 118 | 119 | return retval; 120 | } 121 | 122 | /** 123 | * Returns the array after the doing difference operation to two arrays. 124 | * @param {Array} arr1 The first array. 125 | * @param {Array} arr2 The second array. 126 | * @param {?function(T,T):number=} opt_cmpFn Optional comparison 127 | * function by which the array is to be ordered. It should take 2 arguments to 128 | * compare, and it returns a negative number, zero, or a positive number depending on 129 | * whether the first argument is less than, equal to, or greater than the second argument. 130 | * @return {T[]} The array after the difference operation. 131 | */ 132 | function difference(arr1: T[], arr2: T[], opt_cmpFn: cmpFn = null): T[] { 133 | const cmp = opt_cmpFn || defaultCmp; 134 | const retval = []; 135 | 136 | let i = 0; 137 | let j = 0; 138 | 139 | while (i < arr1.length && j < arr2.length) { 140 | if (cmp(arr1[i], arr2[j]) === 0) { 141 | i++; 142 | j++; 143 | } else if (cmp(arr1[i], arr2[j]) < 0) { 144 | retval.push(arr1[i]); 145 | i++; 146 | } else { 147 | j++; 148 | } 149 | } 150 | if (j === arr2.length) { 151 | for (let k = i; k < arr1.length; ++k) { 152 | retval.push(arr1[k]); 153 | } 154 | } 155 | 156 | return retval; 157 | } 158 | 159 | /** 160 | * Returns the array after the doing symmetric difference operation to two arrays. 161 | * @param {Array} arr1 The first array. 162 | * @param {Array} arr2 The second array. 163 | * @param {?function(T,T):number=} opt_cmpFn Optional comparison 164 | * function by which the array is to be ordered. It should take 2 arguments to 165 | * compare, and it returns a negative number, zero, or a positive number depending on 166 | * whether the first argument is less than, equal to, or greater than the second argument. 167 | * @return {T[]} The array after the symmetric difference operation. 168 | */ 169 | function symmetric_difference( 170 | arr1: T[], 171 | arr2: T[], 172 | opt_cmpFn: cmpFn = null 173 | ): T[] { 174 | const cmp = opt_cmpFn || defaultCmp; 175 | const retval = []; 176 | 177 | let i = 0; 178 | let j = 0; 179 | 180 | while (i < arr1.length && j < arr2.length) { 181 | if (cmp(arr1[i], arr2[j]) === 0) { 182 | i++; 183 | j++; 184 | } else if (cmp(arr1[i], arr2[j]) < 0) { 185 | retval.push(arr1[i]); 186 | i++; 187 | } else { 188 | retval.push(arr2[j]); 189 | j++; 190 | } 191 | } 192 | if (j === arr2.length) { 193 | for (let k = i; k < arr1.length; ++k) { 194 | retval.push(arr1[k]); 195 | } 196 | } else { 197 | for (let k = j; k < arr2.length; ++k) { 198 | retval.push(arr2[k]); 199 | } 200 | } 201 | 202 | return retval; 203 | } 204 | 205 | /** 206 | * Returns the array after the doing merge operation to two arrays. 207 | * @param {Array} arr1 The first array. 208 | * @param {Array} arr2 The second array. 209 | * @param {?function(T,T):number=} opt_cmpFn Optional comparison 210 | * function by which the array is to be ordered. It should take 2 arguments to 211 | * compare, and it returns a negative number, zero, or a positive number depending on 212 | * whether the first argument is less than, equal to, or greater than the second argument. 213 | * @return {T[]} The array after the merge operation. 214 | */ 215 | function merge(arr1: T[], arr2: T[], opt_cmpFn: cmpFn = null): T[] { 216 | const cmp = opt_cmpFn || defaultCmp; 217 | const retval = []; 218 | 219 | let i = 0; 220 | let j = 0; 221 | 222 | while (i < arr1.length && j < arr2.length) { 223 | if (cmp(arr1[i], arr2[j]) === 0) { 224 | retval.push(arr1[i]); 225 | retval.push(arr2[j]); 226 | i++; 227 | j++; 228 | } else if (cmp(arr1[i], arr2[j]) < 0) { 229 | retval.push(arr1[i]); 230 | i++; 231 | } else { 232 | retval.push(arr2[j]); 233 | j++; 234 | } 235 | } 236 | if (j === arr2.length) { 237 | for (let k = i; k < arr1.length; ++k) { 238 | retval.push(arr1[k]); 239 | } 240 | } else { 241 | for (let k = j; k < arr2.length; ++k) { 242 | retval.push(arr2[k]); 243 | } 244 | } 245 | 246 | return retval; 247 | } 248 | 249 | /** 250 | * Returns void after the doing merge operation inplace to the argument array. 251 | * @param {Array} arr The array. 252 | * @param {number} middle The index of the array that separates it to 2 sorted arrays. 253 | * @param {?function(T,T):number=} opt_cmpFn Optional comparison 254 | * function by which the array is to be ordered. It should take 2 arguments to 255 | * compare, and it returns a negative number, zero, or a positive number depending on 256 | * whether the first argument is less than, equal to, or greater than the second argument. 257 | * @return {void} 258 | */ 259 | function inplace_merge( 260 | arr: T[], 261 | middle: number, 262 | opt_cmpFn: cmpFn = null 263 | ): void { 264 | const cmp = opt_cmpFn || defaultCmp; 265 | const helper = []; 266 | 267 | let i = 0; 268 | let j = middle; 269 | 270 | while (i < middle && j < arr.length) { 271 | if (cmp(arr[i], arr[j]) === 0) { 272 | helper.push(arr[i]); 273 | helper.push(arr[j]); 274 | i++; 275 | j++; 276 | } else if (cmp(arr[i], arr[j]) < 0) { 277 | helper.push(arr[i]); 278 | i++; 279 | } else { 280 | helper.push(arr[j]); 281 | j++; 282 | } 283 | } 284 | if (j === arr.length) { 285 | for (let k = i; k < middle; ++k) { 286 | helper.push(arr[k]); 287 | } 288 | } else { 289 | for (let k = j; k < arr.length; ++k) { 290 | helper.push(arr[k]); 291 | } 292 | } 293 | 294 | for (let k = 0; k < arr.length; ++k) { 295 | arr[k] = helper[k]; 296 | } 297 | } 298 | 299 | /** 300 | * Returns true/false after finding out if all the second array elements are in the first array. 301 | * Returns true if all the second array elements are in the first array. False otherwise. 302 | * @param {Array} arr1 The first array. 303 | * @param {Array} arr2 The second array. 304 | * @param {?function(T,T):number=} opt_cmpFn Optional comparison 305 | * function by which the array is to be ordered. It should take 2 arguments to 306 | * compare, and it returns a negative number, zero, or a positive number depending on 307 | * whether the first argument is less than, equal to, or greater than the second argument. 308 | * @return {boolean} 309 | */ 310 | function includes( 311 | arr1: T[], 312 | arr2: T[], 313 | opt_cmpFn: cmpFn = null 314 | ): boolean { 315 | const cmp = opt_cmpFn || defaultCmp; 316 | 317 | let i = 0; 318 | let j = 0; 319 | 320 | while (i < arr1.length && j < arr2.length) { 321 | if (cmp(arr1[i], arr2[j]) === 0) { 322 | i++; 323 | j++; 324 | } else if (cmp(arr1[i], arr2[j]) < 0) { 325 | i++; 326 | } else { 327 | return false; 328 | } 329 | } 330 | return j === arr2.length; 331 | } 332 | 333 | /** 334 | * Returns void after inserting the argument value to the argument array. 335 | * @param {Array} arr The array. 336 | * @param {T} elem The value. 337 | * @param {?function(T,T):number=} opt_cmpFn Optional comparison 338 | * function by which the array is to be ordered. It should take 2 arguments to 339 | * compare, and it returns a negative number, zero, or a positive number depending on 340 | * whether the first argument is less than, equal to, or greater than the second argument. 341 | * @return {void} 342 | */ 343 | function insert(arr: T[], elem: T, opt_cmpFn: cmpFn = null): void { 344 | const cmp = opt_cmpFn || defaultCmp; 345 | 346 | let i = 0; 347 | for (; i < arr.length; ++i) { 348 | if (cmp(elem, arr[i]) < 0) { 349 | break; 350 | } 351 | } 352 | 353 | arr.push(arr[arr.length - 1]); 354 | for (let j = arr.length - 2; j > i; --j) { 355 | arr[j] = arr[j - 1]; 356 | } 357 | arr[i] = elem; 358 | } 359 | 360 | /** 361 | * Returns true/false after removing the argument value from the argument array. 362 | * Returns true if the value is in the array. False otherwise. 363 | * @param {Array} arr The array. 364 | * @param {T} elem The value. 365 | * @param {?function(T,T):number=} opt_cmpFn Optional comparison 366 | * function by which the array is to be ordered. It should take 2 arguments to 367 | * compare, and it returns a negative number, zero, or a positive number depending on 368 | * whether the first argument is less than, equal to, or greater than the second argument. 369 | * @return {boolean} 370 | */ 371 | function remove(arr: T[], elem: T, opt_cmpFn: cmpFn = null): boolean { 372 | const cmp = opt_cmpFn || defaultCmp; 373 | 374 | let i = 0; 375 | for (; i < arr.length; ++i) { 376 | if (cmp(elem, arr[i]) === 0) { 377 | break; 378 | } 379 | } 380 | if (i === arr.length) { 381 | return false; 382 | } 383 | 384 | for (let j = i; j < arr.length - 1; ++j) { 385 | arr[j] = arr[j + 1]; 386 | } 387 | arr.pop(); 388 | return true; 389 | } 390 | 391 | /** 392 | * Returns an index of the search value of the array if the search value is found, 393 | * or returns -1 if it is not found. 394 | * @param {Array} arr The array. 395 | * @param {T} elem The value. 396 | * @param {?function(T,T):number=} opt_cmpFn Optional comparison 397 | * function by which the array is to be ordered. It should take 2 arguments to 398 | * compare, and it returns a negative number, zero, or a positive number depending on 399 | * whether the first argument is less than, equal to, or greater than the second argument. 400 | * @return {number} 401 | */ 402 | function binary_search( 403 | arr: T[], 404 | elem: T, 405 | opt_cmpFn: cmpFn = null 406 | ): number { 407 | const cmp = opt_cmpFn || defaultCmp; 408 | 409 | let i = 0; 410 | let j = arr.length - 1; 411 | let mid = 0; 412 | 413 | while (i <= j) { 414 | mid = i + Math.floor((j - i) / 2); 415 | 416 | if (cmp(elem, arr[mid]) === 0) { 417 | return mid; 418 | } else if (cmp(elem, arr[mid]) < 0) { 419 | j = mid - 1; 420 | } else { 421 | i = mid + 1; 422 | } 423 | } 424 | return -1; 425 | } 426 | 427 | /** 428 | * Returns the index of the leftmost value of the array that is >= the search value, 429 | * or returns the array length if the search value > all values of the array. 430 | * @param {Array} arr The array. 431 | * @param {T} elem The value. 432 | * @param {?function(T,T):number=} opt_cmpFn Optional comparison 433 | * function by which the array is to be ordered. It should take 2 arguments to 434 | * compare, and it returns a negative number, zero, or a positive number depending on 435 | * whether the first argument is less than, equal to, or greater than the second argument. 436 | * @return {number} 437 | */ 438 | function binary_search_ge( 439 | arr: T[], 440 | elem: T, 441 | opt_cmpFn: cmpFn = null 442 | ): number { 443 | const cmp = opt_cmpFn || defaultCmp; 444 | 445 | if (arr.length === 0) { 446 | return 0; 447 | } 448 | 449 | let low = 0; 450 | let high = arr.length - 1; 451 | let mid = 0; 452 | 453 | while (low < high) { 454 | mid = low + Math.floor((high - low) / 2); 455 | 456 | if (cmp(elem, arr[mid]) <= 0) { 457 | high = mid; 458 | } else { 459 | low = mid + 1; 460 | } 461 | } 462 | 463 | if (cmp(arr[low], elem) < 0) { 464 | low++; 465 | } 466 | 467 | return low; 468 | } 469 | 470 | /** 471 | * Returns the index of the leftmost value of the array that is > the search value, 472 | * or returns the array length if the search value >= all values of the array. 473 | * @param {Array} arr The array. 474 | * @param {T} elem The value. 475 | * @param {?function(T,T):number=} opt_cmpFn Optional comparison 476 | * function by which the array is to be ordered. It should take 2 arguments to 477 | * compare, and it returns a negative number, zero, or a positive number depending on 478 | * whether the first argument is less than, equal to, or greater than the second argument. 479 | * @return {number} 480 | */ 481 | function binary_search_gt( 482 | arr: T[], 483 | elem: T, 484 | opt_cmpFn: cmpFn = null 485 | ): number { 486 | const cmp = opt_cmpFn || defaultCmp; 487 | 488 | if (arr.length === 0) { 489 | return 0; 490 | } 491 | 492 | let low = 0; 493 | let high = arr.length - 1; 494 | let mid = 0; 495 | 496 | while (low < high) { 497 | mid = low + Math.floor((high - low) / 2); 498 | 499 | if (cmp(elem, arr[mid]) >= 0) { 500 | low = mid + 1; 501 | } else { 502 | high = mid; 503 | } 504 | } 505 | if (cmp(arr[low], elem) <= 0) { 506 | low++; 507 | } 508 | return low; 509 | } 510 | 511 | /** 512 | * Returns 2 indexes l & r of the array while [l, r) is the half-closed interval of where 513 | * the search value begins and ends. Returns l & r as the same index as the next greater element index 514 | * if the search value is not found. Returns l & r as the same index as the array length if the 515 | * the search value is greater than all array elements. 516 | * @param {Array} arr The array. 517 | * @param {T} elem The value. 518 | * @param {?function(T,T):number=} opt_cmpFn Optional comparison 519 | * function by which the array is to be ordered. It should take 2 arguments to 520 | * compare, and it returns a negative number, zero, or a positive number depending on 521 | * whether the first argument is less than, equal to, or greater than the second argument. 522 | * @return {number[]} 523 | */ 524 | function equal_range( 525 | arr: T[], 526 | elem: T, 527 | opt_cmpFn: cmpFn = null 528 | ): number[] { 529 | const cmp = opt_cmpFn || defaultCmp; 530 | 531 | return [binary_search_ge(arr, elem, cmp), binary_search_gt(arr, elem, cmp)]; 532 | } 533 | 534 | module.exports = { 535 | union: union, 536 | intersection: intersection, 537 | difference: difference, 538 | symmetric_difference: symmetric_difference, 539 | merge: merge, 540 | inplace_merge: inplace_merge, 541 | includes: includes, 542 | insert: insert, 543 | remove: remove, 544 | binary_search: binary_search, 545 | binary_search_ge: binary_search_ge, 546 | binary_search_gt: binary_search_gt, 547 | equal_range: equal_range, 548 | }; 549 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, /* For generating .d.ts file while building the module files */ 4 | "removeComments": true, 5 | "esModuleInterop": true, /* For preventing a warning message from being displayed while running the test code */ 6 | }, 7 | "include": ["src/**/*.ts"], /* For running the test code */ 8 | "exclude": ["src/**/*.spec.ts"] /* For excluding the test file in the module while building the module files */ 9 | } --------------------------------------------------------------------------------