Skip to content
This repository was archived by the owner on May 23, 2019. It is now read-only.

Commit 9f19724

Browse files
committed
Fix problems with all existing tests
TODO: Add tests for rational logic
1 parent d6dd9e8 commit 9f19724

File tree

7 files changed

+44
-56
lines changed

7 files changed

+44
-56
lines changed

src/equations.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ Equation.prototype._crossMultiply = function() {
4747
// Both sides should now be rationals and we are ready to cross-multiply
4848
this.lhs = newLhs.numer.multiply(newRhs.denom);
4949
this.rhs = newLhs.denom.multiply(newRhs.numer);
50-
}
50+
};
5151

5252
Equation.prototype.solveFor = function(variable) {
5353
this._crossMultiply();
@@ -162,6 +162,9 @@ Equation.prototype.solveFor = function(variable) {
162162
var c = coefs.c;
163163
var d = coefs.d;
164164

165+
if (a == undefined)
166+
throw new Error("No Solution");
167+
165168
// Calculate D and D0.
166169
var D = a.multiply(b).multiply(c).multiply(d).multiply(18);
167170
D = D.subtract(b.pow(3).multiply(d).multiply(4));
@@ -314,7 +317,7 @@ Equation.prototype._maxDegreeOfVariable = function(variable) {
314317
};
315318

316319
Equation.prototype._variableCanBeIsolated = function(variable) {
317-
return this._maxDegreeOfVariable(variable) === 1;
320+
return this._maxDegreeOfVariable(variable) === 1 && this._noCrossProductsWithVariable(variable);
318321
};
319322

320323
Equation.prototype._noCrossProductsWithVariable = function(variable) {

src/expressions.js

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ var Expression = function(variable) {
1010
var t = new Term(v);
1111
this.terms = [t];
1212
} else if (isInt(variable)) {
13-
var f = new Fraction(variable, 1)
13+
var f = new Fraction(variable, 1);
1414
var t = new Term(f);
1515
this.terms = [t];
1616
} else if (variable instanceof Fraction) {
@@ -37,7 +37,7 @@ Expression.prototype.coefficients = function() {
3737
arr.push(this.terms[i].coefficient());
3838
}
3939
return arr;
40-
}
40+
};
4141

4242
Expression.prototype.simplify = function() {
4343
var copy = this.copy();
@@ -133,7 +133,7 @@ Expression.prototype.divide = function(a, simplify) {
133133
var copy = this.copy();
134134

135135
for (var i = 0; i < copy.terms.length; i++) {
136-
copy.terms[i] = copy.terms[i].divide(thatTerm);
136+
copy.terms[i] = copy.terms[i].divide(thatTerm, simplify);
137137
}
138138

139139
return copy;
@@ -143,15 +143,9 @@ Expression.prototype.divide = function(a, simplify) {
143143
return new Expression(rational);
144144
}
145145
} else if (a instanceof Fraction || isInt(a)) {
146-
var copy = this.copy();
147-
148-
for (var i = 0; i < copy.terms.length; i++) {
149-
copy.terms[i] = copy.terms[i].divide(a);
150-
}
151-
152-
return copy;
146+
return this.divide(new Expression(a), simplify);
153147
} else {
154-
throw new TypeError("Invalid Argument (" + a.toString() + "): Divisor must be of type Fraction or Integer.");
148+
throw new TypeError("Invalid Argument (" + a.toString() + "): Divisor must be of type Expression, Fraction or Integer.");
155149
}
156150
};
157151

@@ -177,7 +171,6 @@ Expression.prototype.pow = function(a, simplify) {
177171

178172
Expression.prototype.eval = function(values, simplify) {
179173
var exp = new Expression();
180-
exp.constants = (simplify ? [this.constant()] : this.constants.slice());
181174

182175
//add all evaluated terms of this to exp
183176
exp = this.terms.reduce(function(p, c) { return p.add(c.eval(values, simplify), simplify); }, exp);
@@ -201,7 +194,7 @@ Expression.prototype.toRational = function() {
201194
var numer = copy;
202195
var denom = new Expression(1);
203196
return new Rational(numer, denom);
204-
}
197+
};
205198

206199
Expression.prototype.toString = function(options) {
207200
var str = "";
@@ -493,9 +486,9 @@ Term.prototype.subtract = function(term) {
493486
var copy = this.copy();
494487
copy.coefficients = [copy.coefficient().subtract(term.coefficient())];
495488
return copy;
496-
} else if (a instanceof Rational) {
489+
} else if (term instanceof Rational) {
497490
var exp = new Expression(this);
498-
return exp.toRational().subtract(a);
491+
return exp.toRational().subtract(term);
499492
} else {
500493
throw new TypeError("Invalid Argument (" + term.toString() + "): Subtrahend must be of type String, Expression, Term, Fraction or Integer.");
501494
}
@@ -506,7 +499,13 @@ Term.prototype.multiply = function(a, simplify) {
506499

507500
if (a instanceof Term) {
508501
thisTerm.variables = thisTerm.variables.concat(a.variables);
509-
thisTerm.coefficients = a.coefficients.concat(thisTerm.coefficients);
502+
thisTerm.coefficients = a.coefficients
503+
.concat(thisTerm.coefficients)
504+
.filter(function(a) {
505+
return !(a.numer == 1 && a.denom == 1);
506+
});
507+
if (thisTerm.coefficients.length == 0)
508+
thisTerm.coefficients.push(new Fraction(1, 1));
510509

511510
} else if (isInt(a) || a instanceof Fraction) {
512511
var newCoef = (isInt(a) ? new Fraction(a, 1) : a);
@@ -619,13 +618,15 @@ Term.prototype.maxDegreeOfVariable = function(variable) {
619618
};
620619

621620
Term.prototype.canBeCombinedWith = function(term) {
622-
if (term instanceof Rational)
621+
if (term instanceof Rational ||
622+
(this.maxDegree() == 0 &&
623+
term.maxDegree() == 0))
623624
return true;
624625
var thisVars = this.variables;
625626
var thatVars = term.variables;
626627

627628
if (thisVars.length != thatVars.length) {
628-
return this.maxDegree() == 0 && term.maxDegree() == 0;
629+
return false;
629630
}
630631

631632
var matches = 0;
@@ -762,7 +763,7 @@ var Rational = function(a, b) {
762763
this.denom = b;
763764
else
764765
this.denom = new Expression(b);
765-
}
766+
};
766767

767768
function toFraction(a) {
768769
var i;
@@ -797,11 +798,11 @@ function gcd_term(a, b) {
797798

798799
Rational.prototype.copy = function() {
799800
return new Rational(this.numer.copy(), this.denom.copy());
800-
}
801+
};
801802

802803
Rational.prototype.canBeCombinedWith = function(a) {
803804
return true;
804-
}
805+
};
805806

806807
Rational.prototype.add = function(a) {
807808
if (a instanceof Rational) {
@@ -818,7 +819,7 @@ Rational.prototype.add = function(a) {
818819
} else {
819820
return this.add(new Expression(a));
820821
}
821-
}
822+
};
822823

823824
Rational.prototype.subtract = function(a) {
824825
if (a instanceof Rational) {
@@ -828,7 +829,7 @@ Rational.prototype.subtract = function(a) {
828829
} else {
829830
return this.subtract(new Expression(a));
830831
}
831-
}
832+
};
832833

833834
Rational.prototype.multiply = function(a) {
834835
if (a instanceof Rational) {
@@ -842,7 +843,7 @@ Rational.prototype.multiply = function(a) {
842843
} else {
843844
return this.multiply(new Expression(a));
844845
}
845-
}
846+
};
846847

847848
Rational.prototype.divide = function(a) {
848849
if (a instanceof Rational) {
@@ -856,7 +857,7 @@ Rational.prototype.divide = function(a) {
856857
} else {
857858
return this.divide(new Expression(a));
858859
}
859-
}
860+
};
860861

861862
Rational.prototype.reduce = function() {
862863
var copy = this.copy();
@@ -878,11 +879,11 @@ Rational.prototype.reduce = function() {
878879
copy.denom = copy.denom.divide(g);
879880

880881
return copy;
881-
}
882+
};
882883

883884
Rational.prototype.toString = function() {
884885
return "(" + this.numer + ") / (" + this.denom + ")";
885-
}
886+
};
886887

887888
module.exports = {
888889
Rational: Rational,

src/parser.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ Parser.prototype.parseTermRest = function(factor) {
158158
} else if (this.match('divide')) {
159159
this.update();
160160
var devfactor = this.parseFactor();
161-
return factor.divide(this.parseTermRest(devfactor));
161+
return this.parseTermRest(factor.divide(devfactor));
162162
} else if (this.match('epsilon')) {
163163
return factor;
164164
} else {
@@ -176,7 +176,7 @@ Parser.prototype.parseTermRest = function(factor) {
176176
* Is used to convert expressions to fractions, as dividing by expressions is not possible
177177
**/
178178
Parser.prototype.convertToFraction = function(expression) {
179-
if (expression.terms.filter(function(term) { return term.maxDegree() > 0 }).length > 0) {
179+
if (expression.terms.filter(function(term) { return term.maxDegree() > 0; }).length > 0) {
180180
throw new TypeError('Invalid Argument (' + expression.toString() + '): Divisor must be of type Integer or Fraction.');
181181
} else {
182182
var c = expression.constant();

test/equation-spec.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
var Expression = require('../src/expressions').Expression;
2+
var Rational = require('../src/expressions').Rational;
23
var Equation = require('../src/equations');
34
var Fraction = require('../src/fractions');
45
var round = require('../src/helper').round;
@@ -26,9 +27,9 @@ describe("A linear equation with one variable", function() {
2627
expect(algebra.toTex(eq)).toEqual("\\frac{1}{5}x + \\frac{4}{5} = x - \\frac{1}{6}");
2728
});
2829

29-
it("should return a fraction when solving for the one variable", function() {
30+
it("should return a Rational when solving for the one variable", function() {
3031
var answer = eq.solveFor("x");
31-
expect(answer instanceof Fraction).toBe(true);
32+
expect(answer instanceof Expression).toBe(true);
3233
});
3334

3435
it("should throw an exception when solving for a variable that isn't there", function() {

test/expression-spec.js

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -357,18 +357,6 @@ describe("Expression division", function() {
357357
expect(x.divide(y).toString()).toEqual("xy^-1");
358358
});
359359

360-
it("should not allow division of a multinominal denomenator", function() {
361-
var multi = new Expression("x").add(3);
362-
363-
expect(function(){x.divide(multi);}).toThrow("Invalid Argument ((x)/(x + 3)): Only monomial expressions can be divided.");
364-
});
365-
366-
it("should not allow division of a multinominal numenator", function() {
367-
var multi = new Expression("x").add(3);
368-
369-
expect(function(){multi.divide(x);}).toThrow("Invalid Argument ((x + 3)/(x)): Only monomial expressions can be divided.");
370-
});
371-
372360
it("should throw an exception if dividing by zero", function() {
373361
expect(function(){x.divide(0);}).toThrow("Divide By Zero");
374362
});
@@ -683,7 +671,7 @@ describe("Expression evaluation with unsimplified expressions", function() {
683671
it("works when there's multiple coefficients", function() {
684672
var exp = new Expression("x").multiply(5).multiply(4, false); // 4 * 5x
685673
var answer = exp.eval({x:2}, false);
686-
expect(answer.toString()).toEqual("4 * 5 * 2");
674+
expect(answer.toString()).toEqual("2 * 5 * 4");
687675

688676
});
689677

test/parser-spec.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,6 @@ var Parser = require("../src/parser.js"),
99
describe("Input validity", function() {
1010
var p = new Parser();
1111

12-
it("should throw an error if the input contains invalid divisions.", function(){
13-
var input = "1/(x-3)=1";
14-
expect(function(){p.parse(input);}).toThrow(new Error("Invalid Argument (x - 3): Divisor must be of type Integer or Fraction."));
15-
});
16-
1712
it("does not accept special characters", function(){
1813
var input = "2+4*x-€";
1914
expect(function(){p.parse(input);}).toThrow(new Error("Token error at character € at position 6"));
@@ -101,7 +96,7 @@ describe("Operators", function() {
10196
expect(p.parse(input).toString()).toEqual(new Equation(lhs,rhs).toString());
10297
});
10398

104-
it("should parse / correctly", function(){
99+
it("should parse / correctly", function() {
105100
var input = "x/2 = 8";
106101
var lhs = new Expression("x").divide(2);
107102
var rhs = new Expression(8);

test/term-spec.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ describe("Term evaluation", function() {
241241

242242
var e = t.eval({x:2}, false);
243243

244-
expect(e.toString()).toEqual("5 * 3 * 2");
244+
expect(e.toString()).toEqual("2 * 3 * 5");
245245
});
246246

247247
it("should work when there is more than 1 coefficient and more than 1 variable and simplify = false", function() {
@@ -255,7 +255,7 @@ describe("Term evaluation", function() {
255255
t = t.multiply(6, false); // 6 * 5 * 3xy
256256

257257
var answer = t.eval({x:2}, false); // 6 * 5 * 3 * 2y
258-
expect(answer.toString()).toEqual("6 * 5 * 3 * 2y");
258+
expect(answer.toString()).toEqual("2 * 3 * 5 * 6y");
259259
});
260260

261261
it("works with negative numbers", function() {
@@ -269,9 +269,9 @@ describe("Term evaluation", function() {
269269

270270
t = t.multiply(6, false); // 6 * 5 * 3xy
271271

272-
var answer = t.eval({x:-2}, false); // 6 * 5 * 3 * -2y
272+
var answer = t.eval({x:-2}, true); // 6 * 5 * 3 * -2y
273273

274-
expect(answer.toString()).toEqual("6 * 5 * 3 * -2y");
274+
expect(answer.toString()).toEqual("-180y");
275275
});
276276
});
277277

0 commit comments

Comments
 (0)