Added Sigma operator – support for more complex operators 🌟
Fix README.md links pointing to Equation.js instead of Equation Bump version to 1.3.0
This commit is contained in:
33
dist/index.js
vendored
33
dist/index.js
vendored
@@ -107,6 +107,13 @@ var Equation = {
|
||||
};
|
||||
},
|
||||
|
||||
// 2x + 5x * x => 7x^2
|
||||
simplify: function simplify(expression) {
|
||||
var stack = parseExpression(expression);
|
||||
|
||||
console.log(stack);
|
||||
},
|
||||
|
||||
registerOperator: function registerOperator(key, options) {
|
||||
_operators2['default'][key] = options;
|
||||
},
|
||||
@@ -127,7 +134,13 @@ var solveStack = (function (_solveStack) {
|
||||
|
||||
return solveStack;
|
||||
})(function (stack) {
|
||||
if (stack.some(Array.isArray)) {
|
||||
// if an operator takes an expression argument, we should not dive into it
|
||||
// and solve the expression inside
|
||||
var hasExpressionArgument = stack.some(function (a) {
|
||||
return _operators2['default'][a] && _operators2['default'][a].hasExpression;
|
||||
});
|
||||
|
||||
if (!hasExpressionArgument && stack.some(Array.isArray)) {
|
||||
stack = stack.map(function (group) {
|
||||
if (!Array.isArray(group)) {
|
||||
return group;
|
||||
@@ -159,6 +172,12 @@ var MIN_PRECEDENCE = Math.min.apply(Math, _toConsumableArray(PRECEDENCES));
|
||||
* The parsed array
|
||||
*/
|
||||
var parseExpression = function parseExpression(expression) {
|
||||
// function arguments can be separated using comma,
|
||||
// but we parse as groups, so this is the solution to getting comma to work
|
||||
// sigma(0, 4, 2@) becomes sigma(0)(4)(2@) so every argument is parsed
|
||||
// separately
|
||||
expression = expression.replace(/,/g, ')(');
|
||||
|
||||
var stream = new _ReadStream2['default'](expression),
|
||||
stack = [],
|
||||
record = '',
|
||||
@@ -238,19 +257,19 @@ var parseExpression = function parseExpression(expression) {
|
||||
*/
|
||||
var parseGroups = function parseGroups(stack) {
|
||||
// Parantheses become inner arrays which will then be processed first
|
||||
var sub = 0;
|
||||
var depth = 0;
|
||||
return stack.reduce(function (a, b) {
|
||||
if (b.indexOf('(') > -1) {
|
||||
if (b.length > 1) {
|
||||
_.dive(a, sub).push(b.replace('(', ''), []);
|
||||
_.dive(a, depth).push(b.replace('(', ''), []);
|
||||
} else {
|
||||
_.dive(a, sub).push([]);
|
||||
_.dive(a, depth).push([]);
|
||||
}
|
||||
sub++;
|
||||
depth++;
|
||||
} else if (b === ')') {
|
||||
sub--;
|
||||
depth--;
|
||||
} else {
|
||||
_.dive(a, sub).push(b);
|
||||
_.dive(a, depth).push(b);
|
||||
}
|
||||
return a;
|
||||
}, []);
|
||||
|
29
dist/operators.js
vendored
29
dist/operators.js
vendored
@@ -1,8 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; };
|
||||
|
||||
Object.defineProperty(exports, '__esModule', {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _Equation = require('equation');
|
||||
|
||||
var _Equation2 = _interopRequireWildcard(_Equation);
|
||||
|
||||
/*
|
||||
* Operators and Functions
|
||||
* fn: function used to evaluate value
|
||||
@@ -11,6 +18,11 @@ Object.defineProperty(exports, '__esModule', {
|
||||
* e.g: factorial is 01, add is 010, like 2!, 2+2
|
||||
* precedence: determines which operators should be evaluated first
|
||||
* the lower the value, the higher the precedence
|
||||
* hasExpression: determines if any of the operator arguments are an expression
|
||||
* This way, arguments will not be solved by equation and instead
|
||||
* you have to call solve on each argument yourself.
|
||||
* You get the arguments as parsed arrays sigma(0, 5, 2@) becomes
|
||||
* sigma(0, 5, [2, '*', '@']). See sigma operator for reference
|
||||
*/
|
||||
exports['default'] = {
|
||||
'^': {
|
||||
@@ -119,6 +131,23 @@ exports['default'] = {
|
||||
fn: Math.floor,
|
||||
format: '10',
|
||||
precedence: -1
|
||||
},
|
||||
sigma: {
|
||||
fn: function fn(from, to, expression) {
|
||||
var expr = expression.join('').replace(/,/g, '');
|
||||
var regex = new RegExp(ITERATOR_SIGN, 'g');
|
||||
|
||||
var sum = 0;
|
||||
for (var i = from; i <= to; i++) {
|
||||
sum += _Equation2['default'].solve(expr.replace(regex, i));
|
||||
}
|
||||
return sum;
|
||||
},
|
||||
format: '1000',
|
||||
hasExpression: true,
|
||||
precedence: -1
|
||||
}
|
||||
};
|
||||
|
||||
var ITERATOR_SIGN = '@';
|
||||
module.exports = exports['default'];
|
20
dist/tests/solve.js
vendored
20
dist/tests/solve.js
vendored
@@ -92,7 +92,25 @@ describe('Constats', function () {
|
||||
_expect.expect(_M2['default'].solve('sin(PI/2)')).to.equal(1);
|
||||
});
|
||||
|
||||
it('should work for functions as constants', function () {
|
||||
it('should work for functions as constants - retry on fail', function () {
|
||||
_expect.expect(_M2['default'].solve('RAND')).to.not.equal(_M2['default'].solve('RAND'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('Sigma', function () {
|
||||
it('should work with simple expressions', function () {
|
||||
_expect.expect(_M2['default'].solve('sigma(0, 5, @)')).to.equal(15);
|
||||
});
|
||||
|
||||
it('should work with more complex expressions', function () {
|
||||
_expect.expect(_M2['default'].solve('sigma(0, 2, 2@+5)')).to.equal(21);
|
||||
});
|
||||
|
||||
it('should work without an iterator sign', function () {
|
||||
_expect.expect(_M2['default'].solve('sigma(0, 2, 5*2)')).to.equal(30);
|
||||
});
|
||||
|
||||
it('should work with negative start / end points', function () {
|
||||
_expect.expect(_M2['default'].solve('sigma(-5, -2, @)')).to.equal(-14);
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user