@jacksontian/equation-resolver 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Jackson Tian
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md CHANGED
@@ -1,12 +1,18 @@
1
1
  # 方程求解器
2
2
 
3
+ [![Node.js CI](https://github.com/JacksonTian/equation-resolver/actions/workflows/nodejs.yml/badge.svg)](https://github.com/JacksonTian/equation-resolver/actions/workflows/nodejs.yml)
4
+ [![codecov](https://codecov.io/gh/JacksonTian/equation-resolver/branch/main/graph/badge.svg)](https://codecov.io/gh/JacksonTian/equation-resolver)
3
5
  [![npm version](https://img.shields.io/npm/v/@jacksontian/equation-resolver.svg)](https://www.npmjs.com/package/@jacksontian/equation-resolver)
4
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
- [![Node.js Version](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg)](https://nodejs.org/)
6
- [![GitHub repository](https://img.shields.io/badge/GitHub-repository-blue.svg)](https://github.com/JacksonTian/equation-resolver)
7
7
 
8
8
  一个使用词法分析、语法分析和语义分析实现的方程求解程序。
9
9
 
10
+ ## 介绍
11
+
12
+ 当你发现豆包等人工智能工具无法正确识别、无法正确计算结果,导致批改作业费时费力,你需要本方程求解器给你快速的得到确定性的答案。
13
+
14
+ 只要在本程序中输入方程,即可得到解答。快速批改作业,回归亲子时光。
15
+
10
16
  ## 功能特性
11
17
 
12
18
  - 支持线性方程求解
package/lib/evaluator.js CHANGED
@@ -71,10 +71,168 @@ class EquationEvaluator {
71
71
  throw new Error(`Unknown node type: ${node.type}`);
72
72
  }
73
73
 
74
+ // 检查 AST 节点是否包含直接除以指定变量的项(不包括除以 2x 等情况)
75
+ containsDivisionByVariable(node, variable) {
76
+ if (node.type === 'BINARY_OP' && node.op === '/') {
77
+ // 只检查右操作数是否直接是变量(不包括 2x 等情况)
78
+ if (node.right.type === 'VARIABLE' && node.right.name === variable) {
79
+ return true;
80
+ }
81
+ // 递归检查左右子树
82
+ return this.containsDivisionByVariable(node.left, variable) ||
83
+ this.containsDivisionByVariable(node.right, variable);
84
+ } else if (node.type === 'BINARY_OP') {
85
+ return this.containsDivisionByVariable(node.left, variable) ||
86
+ this.containsDivisionByVariable(node.right, variable);
87
+ }
88
+ return false;
89
+ }
90
+
91
+ // 检查 AST 节点是否包含除以包含指定变量的表达式(如 3x, 2x 等)
92
+ containsDivisionByVariableExpression(node, variable) {
93
+ if (node.type === 'BINARY_OP' && node.op === '/') {
94
+ // 检查右操作数是否包含变量
95
+ if (this.containsVariable(node.right, variable)) {
96
+ return { found: true, divisor: node.right };
97
+ }
98
+ // 递归检查左右子树
99
+ const leftResult = this.containsDivisionByVariableExpression(node.left, variable);
100
+ if (leftResult.found) return leftResult;
101
+ const rightResult = this.containsDivisionByVariableExpression(node.right, variable);
102
+ if (rightResult.found) return rightResult;
103
+ } else if (node.type === 'BINARY_OP') {
104
+ const leftResult = this.containsDivisionByVariableExpression(node.left, variable);
105
+ if (leftResult.found) return leftResult;
106
+ const rightResult = this.containsDivisionByVariableExpression(node.right, variable);
107
+ if (rightResult.found) return rightResult;
108
+ }
109
+ return { found: false, divisor: null };
110
+ }
111
+
112
+ // 检查 AST 节点是否包含指定变量
113
+ containsVariable(node, variable) {
114
+ if (node.type === 'VARIABLE') {
115
+ return node.name === variable;
116
+ } else if (node.type === 'BINARY_OP') {
117
+ return this.containsVariable(node.left, variable) ||
118
+ this.containsVariable(node.right, variable);
119
+ }
120
+ return false;
121
+ }
122
+
123
+ // 将表达式乘以另一个表达式(用于消除除以包含变量的表达式)
124
+ multiplyByExpression(node, expression) {
125
+ if (node.type === 'NUMBER') {
126
+ return {
127
+ type: 'BINARY_OP',
128
+ op: '*',
129
+ left: node,
130
+ right: expression
131
+ };
132
+ }
133
+ if (node.type === 'VARIABLE') {
134
+ return {
135
+ type: 'BINARY_OP',
136
+ op: '*',
137
+ left: node,
138
+ right: expression
139
+ };
140
+ }
141
+ if (node.type === 'BINARY_OP') {
142
+ if (node.op === '/') {
143
+ // 如果除以表达式,直接返回左操作数(不需要再乘以表达式)
144
+ // 这里需要深度比较,简化处理:如果右操作数结构相同,直接返回左操作数
145
+ // 为了简化,我们假设如果右操作数包含变量,就认为匹配
146
+ if (this.isSameExpression(node.right, expression)) {
147
+ return node.left;
148
+ }
149
+ // 否则,左操作数乘以表达式,右操作数保持不变
150
+ return {
151
+ type: 'BINARY_OP',
152
+ op: node.op,
153
+ left: this.multiplyByExpression(node.left, expression),
154
+ right: node.right
155
+ };
156
+ }
157
+ // 对于其他操作符(+、-、*),递归处理左右子树
158
+ return {
159
+ type: 'BINARY_OP',
160
+ op: node.op,
161
+ left: this.multiplyByExpression(node.left, expression),
162
+ right: this.multiplyByExpression(node.right, expression)
163
+ };
164
+ }
165
+ return node;
166
+ }
167
+
168
+ // 简化版的表达式比较(用于判断两个表达式是否相同)
169
+ isSameExpression(expr1, expr2) {
170
+ // 简单的深度比较
171
+ return JSON.stringify(expr1) === JSON.stringify(expr2);
172
+ }
173
+
174
+ // 将表达式乘以变量(用于消除除以变量的项)
175
+ multiplyByVariable(node, variable) {
176
+ if (node.type === 'NUMBER') {
177
+ return {
178
+ type: 'BINARY_OP',
179
+ op: '*',
180
+ left: node,
181
+ right: { type: 'VARIABLE', name: variable }
182
+ };
183
+ }
184
+ if (node.type === 'VARIABLE') {
185
+ return {
186
+ type: 'BINARY_OP',
187
+ op: '*',
188
+ left: node,
189
+ right: { type: 'VARIABLE', name: variable }
190
+ };
191
+ }
192
+ if (node.type === 'BINARY_OP') {
193
+ if (node.op === '/') {
194
+ // 如果除以变量,直接返回左操作数(不需要再乘以变量)
195
+ if (node.right.type === 'VARIABLE' && node.right.name === variable) {
196
+ return node.left;
197
+ }
198
+ // 否则,左操作数乘以变量,右操作数保持不变
199
+ return {
200
+ type: 'BINARY_OP',
201
+ op: node.op,
202
+ left: this.multiplyByVariable(node.left, variable),
203
+ right: node.right
204
+ };
205
+ }
206
+ // 对于其他操作符(+、-、*),递归处理左右子树
207
+ return {
208
+ type: 'BINARY_OP',
209
+ op: node.op,
210
+ left: this.multiplyByVariable(node.left, variable),
211
+ right: this.multiplyByVariable(node.right, variable)
212
+ };
213
+ }
214
+ return node;
215
+ }
216
+
74
217
  // 获取指定变量的系数(支持多变量方程),返回 Fraction
75
218
  getVariableCoefficientFraction(variable, allVariables) {
76
219
  const standardForm = this.toStandardForm();
77
220
 
221
+ // 检查是否包含除以变量的项
222
+ const hasDivision = this.containsDivisionByVariable(standardForm, variable);
223
+
224
+ // 检查是否包含除以包含变量的表达式(如 3x, 2x 等)
225
+ const divisionResult = this.containsDivisionByVariableExpression(standardForm, variable);
226
+
227
+ let formToUse = standardForm;
228
+ if (hasDivision) {
229
+ // 如果包含除以变量的项,将整个表达式乘以变量
230
+ formToUse = this.multiplyByVariable(standardForm, variable);
231
+ } else if (divisionResult.found) {
232
+ // 如果包含除以包含变量的表达式,将整个表达式乘以该表达式
233
+ formToUse = this.multiplyByExpression(standardForm, divisionResult.divisor);
234
+ }
235
+
78
236
  // 使用两个不同的变量值来计算系数
79
237
  const values1 = {};
80
238
  const values0 = {};
@@ -89,9 +247,10 @@ class EquationEvaluator {
89
247
  }
90
248
  });
91
249
 
92
- const val1 = this.evaluateWithValues(standardForm, values1);
93
- const val0 = this.evaluateWithValues(standardForm, values0);
250
+ const val1 = this.evaluateWithValues(formToUse, values1);
251
+ const val0 = this.evaluateWithValues(formToUse, values0);
94
252
 
253
+ // 如果 val0 是 Infinity,使用 x=1 和 x=2 来计算系数
95
254
  if (val0 === Infinity || !val0.isFinite()) {
96
255
  const values2 = {};
97
256
  allVariables.forEach(v => {
@@ -101,8 +260,13 @@ class EquationEvaluator {
101
260
  values2[v] = 0;
102
261
  }
103
262
  });
104
- const val2 = this.evaluateWithValues(standardForm, values2);
105
- return val2.subtract(val1);
263
+ const val2 = this.evaluateWithValues(formToUse, values2);
264
+ if (val2 !== Infinity && val2.isFinite() && val1 !== Infinity && val1.isFinite()) {
265
+ // 使用 val2 - val1 来计算系数
266
+ return val2.subtract(val1);
267
+ }
268
+ // 如果仍然有问题,返回 0(不应该到达这里)
269
+ return new Fraction(0, 1);
106
270
  }
107
271
 
108
272
  return val1.subtract(val0);
@@ -125,11 +289,33 @@ class EquationEvaluator {
125
289
  const val0 = this.evaluateWithValues(standardForm, values);
126
290
 
127
291
  if (val0 === Infinity || !val0.isFinite()) {
292
+ // 检查是否包含直接除以变量的项(检查所有变量)
293
+ let hasDivision = false;
294
+ let formToUse = standardForm;
295
+ for (const variable of allVariables) {
296
+ if (this.containsDivisionByVariable(standardForm, variable)) {
297
+ hasDivision = true;
298
+ formToUse = this.multiplyByVariable(standardForm, variable);
299
+ break; // 只需要转换一次
300
+ }
301
+ }
302
+
303
+ // 如果没有直接除以变量的项,检查是否包含除以包含变量的表达式
304
+ if (!hasDivision) {
305
+ for (const variable of allVariables) {
306
+ const divisionResult = this.containsDivisionByVariableExpression(standardForm, variable);
307
+ if (divisionResult.found) {
308
+ formToUse = this.multiplyByExpression(standardForm, divisionResult.divisor);
309
+ break; // 只需要转换一次
310
+ }
311
+ }
312
+ }
313
+
128
314
  const values1 = {};
129
315
  allVariables.forEach(v => {
130
316
  values1[v] = 1;
131
317
  });
132
- const val1 = this.evaluateWithValues(standardForm, values1);
318
+ const val1 = this.evaluateWithValues(formToUse, values1);
133
319
 
134
320
  // 计算所有变量的系数和
135
321
  let totalCoeff = new Fraction(0, 1);
package/lib/fraction.js CHANGED
@@ -19,8 +19,17 @@ class Fraction {
19
19
 
20
20
  // 最大公约数
21
21
  gcd(a, b) {
22
+ // 处理 Infinity 和 NaN
23
+ if (!isFinite(a) || !isFinite(b)) {
24
+ return 1;
25
+ }
22
26
  if (b === 0) return a;
23
- return this.gcd(b, a % b);
27
+ const remainder = a % b;
28
+ // 如果 remainder 是 NaN 或 Infinity,返回 1
29
+ if (!isFinite(remainder)) {
30
+ return 1;
31
+ }
32
+ return this.gcd(b, remainder);
24
33
  }
25
34
 
26
35
  // 从字符串创建分数(支持整数和小数)
package/package.json CHANGED
@@ -1,16 +1,20 @@
1
1
  {
2
2
  "name": "@jacksontian/equation-resolver",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "type": "module",
5
5
  "description": "解方程程序",
6
6
  "main": "lib/index.js",
7
7
  "bin": {
8
- "solve": "./bin/cli.js"
8
+ "solve": "bin/cli.js"
9
9
  },
10
+ "files": [
11
+ "lib",
12
+ "bin"
13
+ ],
10
14
  "scripts": {
11
15
  "dev": "node --test",
12
16
  "test": "node --test test/*.test.js",
13
- "test:cov": "c8 --reporter=html --reporter=text npm run test",
17
+ "test:cov": "c8 --reporter=html --reporter=lcov --reporter=text npm run test",
14
18
  "dev:cov": "c8 --reporter=html --reporter=text npm run dev",
15
19
  "lint": "eslint .",
16
20
  "lint:fix": "eslint . --fix"
@@ -22,7 +26,7 @@
22
26
  "author": "Jackson Tian",
23
27
  "repository": {
24
28
  "type": "git",
25
- "url": "https://github.com/JacksonTian/equation-resolver.git"
29
+ "url": "git+https://github.com/JacksonTian/equation-resolver.git"
26
30
  },
27
31
  "homepage": "https://github.com/JacksonTian/equation-resolver",
28
32
  "license": "MIT",
@@ -1,31 +0,0 @@
1
- # This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
2
- # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
3
-
4
- name: Node.js CI
5
-
6
- on:
7
- push:
8
- branches: [ "main" ]
9
- pull_request:
10
- branches: [ "main" ]
11
-
12
- jobs:
13
- build:
14
-
15
- runs-on: ubuntu-latest
16
-
17
- strategy:
18
- matrix:
19
- node-version: [18.x, 20.x, 22.x, 24.x]
20
- # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
21
-
22
- steps:
23
- - uses: actions/checkout@v4
24
- - name: Use Node.js ${{ matrix.node-version }}
25
- uses: actions/setup-node@v4
26
- with:
27
- node-version: ${{ matrix.node-version }}
28
- cache: 'npm'
29
- - run: npm ci
30
- - run: npm run build --if-present
31
- - run: npm test
package/eslint.config.js DELETED
@@ -1,63 +0,0 @@
1
- import js from '@eslint/js';
2
-
3
- export default [
4
- js.configs.recommended,
5
- {
6
- languageOptions: {
7
- ecmaVersion: 2024,
8
- sourceType: 'module',
9
- globals: {
10
- console: 'readonly',
11
- process: 'readonly',
12
- Buffer: 'readonly',
13
- __dirname: 'readonly',
14
- __filename: 'readonly',
15
- global: 'readonly',
16
- module: 'readonly',
17
- require: 'readonly',
18
- exports: 'readonly',
19
- },
20
- },
21
- rules: {
22
- 'no-unused-vars': ['error', {
23
- argsIgnorePattern: '^_',
24
- varsIgnorePattern: '^_',
25
- }],
26
- 'no-console': 'off',
27
- 'no-undef': 'error',
28
- 'no-redeclare': 'error',
29
- 'no-constant-condition': 'error',
30
- 'no-empty': 'error',
31
- 'no-extra-semi': 'error',
32
- 'no-func-assign': 'error',
33
- 'no-inner-declarations': 'error',
34
- 'no-sparse-arrays': 'error',
35
- 'no-unreachable': 'error',
36
- 'use-isnan': 'error',
37
- 'valid-typeof': 'error',
38
- 'no-var': 'error',
39
- 'prefer-const': 'error',
40
- 'prefer-arrow-callback': 'error',
41
- 'arrow-body-style': ['error', 'as-needed'],
42
- 'no-duplicate-imports': 'error',
43
- 'no-useless-constructor': 'error',
44
- 'no-useless-return': 'error',
45
- 'prefer-template': 'error',
46
- 'prefer-destructuring': ['error', {
47
- array: false,
48
- object: true,
49
- }],
50
- 'object-shorthand': 'error',
51
- 'prefer-rest-params': 'error',
52
- 'prefer-spread': 'error',
53
- },
54
- },
55
- {
56
- ignores: [
57
- 'node_modules/**',
58
- 'coverage/**',
59
- '*.min.js',
60
- ],
61
- },
62
- ];
63
-
@@ -1,230 +0,0 @@
1
- import { describe, it } from 'node:test';
2
- import assert from 'node:assert';
3
- import { Evaluator } from '../lib/evaluator.js';
4
- import { Lexer } from '../lib/lexer.js';
5
- import { Parser } from '../lib/parser.js';
6
- import { SemanticChecker } from '../lib/semantic-checker.js';
7
-
8
- function solve(input) {
9
- const lexer = new Lexer(input);
10
- const parser = new Parser(lexer);
11
- const ast = parser.parse();
12
- const checker = new SemanticChecker(ast);
13
- checker.check();
14
- const evaluator = new Evaluator(ast);
15
- return evaluator.solve();
16
- }
17
-
18
- describe('solve', () => {
19
- describe('basic linear equation', () => {
20
- it('single variable simple multiplication should be solved', () => {
21
- const result = solve('2x = 4');
22
- assert.strictEqual(result.x, 2);
23
- });
24
-
25
- it('addition', () => {
26
- const result = solve('3x + 2 = 8');
27
- assert.strictEqual(result.x, 2);
28
- });
29
-
30
- it('subtraction', () => {
31
- const result = solve('5x - 3 = 12');
32
- assert.strictEqual(result.x, 3);
33
- });
34
-
35
- it('subtraction and multiplication', () => {
36
- const result = solve('2x - 1 = 5');
37
- assert.strictEqual(result.x, 3);
38
- });
39
- });
40
-
41
- describe('division related', () => {
42
- it('implicit multiplication by division', () => {
43
- const result = solve('8 / 2x = 2');
44
- assert.strictEqual(result.x, 2);
45
- });
46
-
47
- it('implicit multiplication by division 2', () => {
48
- const result = solve('10 / 5x = 1');
49
- assert.strictEqual(result.x, 2);
50
- });
51
-
52
- it('implicit multiplication by division 3', () => {
53
- const result = solve('12 / 3x = 2');
54
- assert.strictEqual(result.x, 2);
55
- });
56
- });
57
-
58
- describe('parentheses and implicit multiplication', () => {
59
- it('parentheses and implicit multiplication', () => {
60
- const result = solve('2(3y-4)=4y-7(4-y)');
61
- assert.strictEqual(result.y, 4);
62
- });
63
-
64
- it('explicit multiplication', () => {
65
- const result = solve('2*(3y-4)=4y-7(4-y)');
66
- assert.strictEqual(result.y, 4);
67
- });
68
-
69
- it('parentheses expression', () => {
70
- const result = solve('3(x+2) = 15');
71
- assert.strictEqual(result.x, 3);
72
- });
73
-
74
- it('parentheses subtraction', () => {
75
- const result = solve('2(x-1) = 6');
76
- assert.strictEqual(result.x, 4);
77
- });
78
- });
79
-
80
- describe('complex equations', () => {
81
- it('complex fraction equation', () => {
82
- const result = solve('(x+3.5)/0.9=15*(x+3.5)-125');
83
- assert.strictEqual(result.x, 5.5);
84
- });
85
-
86
- it('mixed expression', () => {
87
- const result = solve('2x + 3(x-1) = 10');
88
- assert.strictEqual(result.x, 2.6);
89
- });
90
- });
91
-
92
- describe('decimal', () => {
93
- it('decimal coefficient', () => {
94
- const result = solve('0.5x = 2');
95
- assert.strictEqual(result.x, 4);
96
- });
97
-
98
- it('decimal addition of constant', () => {
99
- const result = solve('1.5x + 0.5 = 5');
100
- assert.strictEqual(result.x, 3);
101
- });
102
- });
103
-
104
- // describe('负数', () => {
105
- // it('负变量', () => {
106
- // const result = solve('-x = 5');
107
- // assert.strictEqual(result.x, -5);
108
- // });
109
-
110
- // it('负数结果', () => {
111
- // const result = solve('2x - 10 = -4');
112
- // assert.strictEqual(result.x, 3);
113
- // });
114
- // });
115
-
116
- describe('error cases', () => {
117
- it('identity equation', () => {
118
- assert.throws(
119
- () => solve('2x = 2x'),
120
- (error) => {
121
- assert.strictEqual(error.message, 'Equation has infinite solutions');
122
- return true;
123
- }
124
- );
125
- });
126
-
127
- it('contradictory equation', () => {
128
- assert.throws(
129
- () => solve('2x = 2x + 1'),
130
- (error) => {
131
- assert.strictEqual(error.message, 'Equation system has no solution');
132
- return true;
133
- }
134
- );
135
- });
136
- });
137
-
138
- describe('binary linear equation system', () => {
139
- it('simple binary linear equation system', () => {
140
- const result = solve('x + y = 5; x - y = 1');
141
- assert.strictEqual(result.x, 3);
142
- assert.strictEqual(result.y, 2);
143
- });
144
-
145
- it('binary linear equation system with coefficients', () => {
146
- const result = solve('2x + 3y = 7; 3x - 2y = 4');
147
- assert.strictEqual(result.x, 2);
148
- assert.strictEqual(result.y, 1);
149
- });
150
-
151
- it('binary linear equation system with negative numbers', () => {
152
- const result = solve('x - y = 3; 2x + y = 0');
153
- assert.strictEqual(result.x, 1);
154
- assert.strictEqual(result.y, -2);
155
- });
156
-
157
- it('binary linear equation system with decimals', () => {
158
- const result = solve('0.5x + y = 2; x - 0.5y = 3');
159
- assert.strictEqual(result.x, 3.2);
160
- assert.strictEqual(result.y, 0.4);
161
- });
162
- });
163
-
164
- describe('three linear equation system', () => {
165
- it('simple three linear equation system', () => {
166
- const result = solve('x + y + z = 6; x - y + z = 2; x + y - z = 0');
167
- assert.strictEqual(result.x, 1);
168
- assert.strictEqual(result.y, 2);
169
- assert.strictEqual(result.z, 3);
170
- });
171
-
172
- it('three linear equation system with coefficients', () => {
173
- const result = solve('2x + y - z = 8; x - 2y + 3z = 1; 3x + 2y + z = 9');
174
- assert.strictEqual(result.x, 3.625);
175
- assert.strictEqual(result.y, -0.375);
176
- assert.strictEqual(result.z, -1.125);
177
- });
178
- });
179
-
180
- describe('equation system with parentheses', () => {
181
- it('parentheses expression', () => {
182
- const result = solve('2(x + y) = 6; x - y = 1');
183
- assert.strictEqual(result.x, 2);
184
- assert.strictEqual(result.y, 1);
185
- });
186
-
187
- it('complex parentheses expression', () => {
188
- const result = solve('3(x - 1) + 2y = 5; 2x + (y + 1) = 4');
189
- assert.strictEqual(result.x, -2);
190
- assert.strictEqual(result.y, 7);
191
- });
192
- });
193
-
194
- describe('different variable names', () => {
195
- it('different variable names', () => {
196
- const result = solve('a + b = 5; a - b = 1');
197
- assert.strictEqual(result.a, 3);
198
- assert.strictEqual(result.b, 2);
199
- });
200
-
201
- it('mixed variable names', () => {
202
- const result = solve('x + y = 5; x + z = 6; y + z = 7');
203
- assert.strictEqual(result.x, 2);
204
- assert.strictEqual(result.y, 3);
205
- assert.strictEqual(result.z, 4);
206
- });
207
- });
208
-
209
- describe('equation system error cases', () => {
210
- it('equation count is less than variable count', () => {
211
- assert.throws(
212
- () => solve('x + y = 5'),
213
- (error) => {
214
- assert.strictEqual(error.message, 'Equation count (1) is less than variable count (2)');
215
- return true;
216
- }
217
- );
218
- });
219
-
220
- it('equation system has no solution', () => {
221
- assert.throws(
222
- () => solve('x + y = 5; x + y = 10'),
223
- (error) => {
224
- assert.strictEqual(error.message, 'Equation system has no solution');
225
- return true;
226
- }
227
- );
228
- });
229
- });
230
- });