├── .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 |
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 | }
--------------------------------------------------------------------------------