-
Notifications
You must be signed in to change notification settings - Fork 276
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
adding factoring support #104
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yay factoring! added some thoughts :)
lib/checks/isQuadratic.js
Outdated
|
||
const Node = require('../node'); | ||
|
||
// TODO(ael) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
docstring
lib/checks/isQuadratic.js
Outdated
@@ -0,0 +1,45 @@ | |||
'use strict'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you merge in the new linter changes? apparently we don't need 'use strict'
in modules because they're strict by default (the linter will catch this now 😄 )
lib/checks/isQuadratic.js
Outdated
|
||
// TODO(ael) | ||
function isQuadratic(node) { | ||
if (!Node.Type.isOperator(node) || node.op !== '+') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can now do if (!Node.Type.isOperator(node, '+')
thanks to a recent change :)
lib/checks/isQuadratic.js
Outdated
const constantTerms = node.args.filter(Node.Type.isConstant); | ||
|
||
if (secondDegreeTerms.length !== 1 || firstDegreeTerms.length > 1 || | ||
constantTerms.length !== 1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm why'd you choose this combination?
I agree that there should be a secondDegreeTerm for sure
but what about x^2 + x
? that seems like a quadratic, but there's no constant term
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmmmmm. Interesting. You're right :)
lib/checks/isQuadratic.js
Outdated
|
||
const secondDegreeTerms = node.args.filter(isSecondDegree); | ||
const firstDegreeTerms = node.args.filter(isFirstDegree); | ||
const constantTerms = node.args.filter(Node.Type.isConstant); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if there are other args that don't fall into one of these buckets? we should return false right? so I guess check that the length of each of these add up to the number of args
lib/factor/factorQuadratic.js
Outdated
if (constantTermValue < 0 && | ||
firstTermCoeffRootValue % 1 === 0 && | ||
constantTermRootValue % 1 === 0) { | ||
const polyTerm = Node.Creator.polynomialTerm(symbol, null, firstTermCoeffRootNode); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you split this line into 2 lines? (and everywhere else you have a line like this)
lib/factor/factorQuadratic.js
Outdated
const secondTermCoeffValue = secondTermNode.getCoeffValue(); | ||
if (secondTermCoeffValue < 0) { | ||
constantTermRootValue = constantTermRootValue * -1; | ||
constantTermRootNode = Negative.negate(constantTermRootNode); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alternatively, you can just make constantTermRootNode
at the times you need it instead of at the beginning
not sure if that's better or not
I have a slight preference for this because it becomes more obvious why you need it
test/factor/factorQuadratic.test.js
Outdated
['x^2 + 4x + 1', 'x^2 + 4x + 1'], | ||
]; | ||
tests.forEach(t => testFactorQuadratic(t[0], t[1])); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add some tests for things that shouldn't factor yet? to make sure we're not treating things as difference of square when they're not, etc.
I'm especially cautious about stuff with signs e.g. -x^2 - 2x - 1
lib/factor/factorQuadratic.js
Outdated
constantTermRootNode = Negative.negate(constantTermRootNode); | ||
} | ||
|
||
const perfectProduct = 2 * firstTermCoeffRootValue * constantTermRootValue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some more comments describing how these variables fit into things might be helpful
I understood what was going on, but had to read over the code a couple times to get it
lib/factor/factorQuadratic.js
Outdated
const factorPairs = ConstantFactors.getFactorPairs(constantTermValue, true); | ||
for (const pair of factorPairs) { | ||
if (pair[0] + pair[1] === secondTermCoeffValue) { | ||
const polyTerm = Node.Creator.polynomialTerm(symbol, null, firstTermCoeffRootNode); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we know that the coeff is 1, so the polyTerm is just the symbol right?
lib/checks/isQuadratic.js
Outdated
return false; | ||
} | ||
|
||
if (node.args.length > 3) { | ||
return false; | ||
} | ||
|
||
const secondDegreeTerms = node.args.filter(isSecondDegree); | ||
const firstDegreeTerms = node.args.filter(isFirstDegree); | ||
const symbolSet = Symbols.getSymbolsInExpression(node); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this might be confusing to an outsider - add a comment explaining what this is checking?
lib/checks/isQuadratic.js
Outdated
return exponent && exponent.value === '2'; | ||
} | ||
return false; | ||
function isPolynomialTermOfDegree(degree) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add a docstring that also makes it clear we have to pass a string as the degree (which is unfortunate :p)
lib/checks/isQuadratic.js
Outdated
const exponent = polyTerm.getExponentNode(true); | ||
return exponent && exponent.value === '1'; | ||
// check that there are no terms that don't fall into these groups | ||
if (secondDegreeTerms.length + firstDegreeTerms.length + constantTerms.length !== node.args.length) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
line is too long, idk how strict we wanna be about this though
lib/factor/factorQuadratic.js
Outdated
@@ -21,19 +20,20 @@ function factorQuadratic(node) { | |||
} | |||
|
|||
// get a, b and c | |||
let firstTermNode, secondTermNode, constantTermValue; | |||
let symbol, aValue, bValue, cValue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe have them default to 0? what happens if they don't get set (if those terms aren't there)
lib/factor/factorQuadratic.js
Outdated
} | ||
|
||
// factor sum product rule e.g. x^2 + 3x + 2 | ||
status = factorSumProductRule(node, symbol, aValue, bValue, cValue, negate); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you could loop through these like we do in the other places where we check lots of different simplification functions
lib/factor/factorQuadratic.js
Outdated
const aRootNode = Node.Creator.constant(aRootValue); | ||
|
||
const polyTerm = Node.Creator.polynomialTerm( | ||
symbol, null, aRootNode); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we know that aRootNode is 1 - so you could just not pass aRootNode at all right?
Node.Creator.polynomialTerm(symbol)
@@ -120,6 +121,7 @@ function addNegativeOneCoefficient(node) { | |||
polyTerm.getSymbolNode(), | |||
polyTerm.getExponentNode(), | |||
polyTerm.getCoeffNode(), | |||
false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add a comment for what this means maybe
@@ -84,7 +84,8 @@ function addPositiveOneCoefficient(node) { | |||
newNode.args[i] = Node.Creator.polynomialTerm( | |||
polyTerm.getSymbolNode(), | |||
polyTerm.getExponentNode(), | |||
Node.Creator.constant(1)); | |||
Node.Creator.constant(1), | |||
true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe add comment for what true means
lib/factor/factorQuadratic.js
Outdated
return Node.Status.noChange(node); | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extra line
lib/node/Creator.js
Outdated
@@ -48,12 +48,12 @@ const NodeCreator = { | |||
// exponent might be null, which means there's no exponent node. | |||
// similarly, coefficient might be null, which means there's no coefficient | |||
// the symbol node can never be null. | |||
polynomialTerm (symbol, exponent, coeff, coeffIsNegOne=false) { | |||
polynomialTerm (symbol, exponent, coeff, coeffIsOne=false, coeffIsNegOne=false) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we could combine coeffIsOne
and coeffIsNegOne
to a shared variable... something about explicit coefficients
or is that more confusing?
lib/checks/isQuadratic.js
Outdated
@@ -12,13 +12,14 @@ function isQuadratic(node) { | |||
return false; | |||
} | |||
|
|||
// get the number of symbols in the expression and ensure there's only one |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry I'm being really picky now so you don't have to change this but
I think this comment is pretty close to what the code is doing, I meant more like
"make sure only one symbol appears in the expression, i.e. just x and not both x and y"
the point of confusion for people could be that it's a set (which you show in the var name which is helpful, so it's probably fine) and there can be multiple symbol terms (multiple symbols) as long as they're of the same symbol name
lib/factor/factorQuadratic.js
Outdated
|
||
const polyTerm = Node.Creator.polynomialTerm( | ||
symbol, null, aRootNode); | ||
const polyTerm = Node.Creator.polynomialTerm(symbol, null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh wait you can just use Node.Creator.symbol
I'm worried that |
lib/factor/factorQuadratic.js
Outdated
const exponent = Node.Creator.constant(2); | ||
|
||
if (negate) { | ||
paren = Negative.negate(paren); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you negate before doing the ^2, won't the negating cancel out?
ie (-(x+2))^2
I see your test passes though, which confuses me
still missing tests for |
lib/factor/factorQuadratic.js
Outdated
@@ -56,35 +69,13 @@ function factorQuadratic(node) { | |||
cValue = -cValue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these should default to 0 above, or else negating doesn't really make sense in the null case
added 6 comments, mostly just stuff you missed from the last code review lemme know if there's anything I can do to make it easier for you to see and check off my comments to make sure you address them all (I know github doesn't really do a good job of making it easy) |
…gative and also fixing negation when factoring
👍 |
Issue: #50
Adds support for factoring by:
Quadratic equation to be added in the future. The reason I didn't add it yet is because it requires simplification of only what will be in the brackets (without expansion), and I didn't want to make a decision on how that should happen.