mathsteps-experimental-fork
Version:
Step by step math solutions. Experimental Fork
139 lines (134 loc) • 7.09 kB
JavaScript
;
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const index = require('../index.js');
const myNodeToString = require('./nodeServices/myNodeToString.js');
const parseText = require('./nodeServices/parseText.js');
const removeUnnessaryParenthesis = require('./nodeServices/removeUnnessaryParenthesis.js');
const treeUtil = require('./treeUtil.js');
const kemuSimplifyCommonServices = require('../simplifyExpression/kemuSimplifyCommonServices.js');
const mscNormalizeNodeFunctions = require('../simplifyExpression/mscNormalizeNodeFunctions.js');
const arrayUtils = require('../util/arrayUtils.js');
const cleanString = require('../util/cleanString.js');
const regex = require('../util/regex.js');
const kemuSortArgs = require('../simplifyExpression/kemuSortArgs.js');
const getNodeStepsToSolveExpression = (userStep) => index.default.simplifyExpression({
expressionAsText: cleanString.cleanString(userStep),
isDebugMode: false,
expressionCtx: void 0,
getMistakes: false,
getAllNextStepPossibilities: false,
onStepCb: (step) => {
}
});
function normalizeNodeForEquality(node_) {
let node = typeof node_ === "string" ? parseText.parseText(node_) : node_;
node = mscNormalizeNodeFunctions.convertNumParVarDivNumToNumVarDivNum(node);
node = removeUnnessaryParenthesis.removeUnnecessaryParentheses(node);
node = mscNormalizeNodeFunctions.convertAll1xToX(node);
node = kemuSimplifyCommonServices.kemuFlatten(node);
node = treeUtil.removeImplicitMultiplicationFromNode(node);
node = mscNormalizeNodeFunctions.convertAllSimpleFractionsToDecimals(node);
node = mscNormalizeNodeFunctions.normalizeNegativesAndFractions(node);
node = kemuSimplifyCommonServices.kemuNormalizeConstantNodes(node);
node = mscNormalizeNodeFunctions.convertAll1xToX(node);
node = kemuSortArgs(node, true, true);
return node;
}
function normalizeStringExpressionForEquality(stringExpression) {
stringExpression = cleanString.cleanString(stringExpression);
stringExpression = stringExpression.replace(/\((\d+(\.\d+)?)\)/g, "$1");
stringExpression = stringExpression.replace(/\(-(\d+(\.\d+)?)\)/g, "-$1");
stringExpression = mscNormalizeNodeFunctions.makePlusMinusMinusAndReturnString(`0+${stringExpression}`);
stringExpression = stringExpression.replaceAll(/\b0[a-z]\b/gi, "0");
stringExpression = stringExpression.replaceAll(/\b1([a-z])\b/gi, "$1");
stringExpression = stringExpression.replace(/(\d+)\*([a-z])/gi, "$1$2");
const numberRG = "\\b\\d+(?:\\.\\d+)?[a-z]?\\b";
const regexExp = regex.makeExtendedRegExp(String.raw`\b(${numberRG})-\((${numberRG})/(${numberRG})\)`, "gi");
stringExpression = stringExpression.replace(regexExp, "$1+(-$2/$3)");
stringExpression = cleanString.cleanString(stringExpression);
return stringExpression;
}
function areEquationsEqual(eq0, eq1, equalityCache = null) {
const sides0 = eq0.split("=").map((side) => cleanString.cleanString(side));
const sides1 = eq1.split("=").map((side) => cleanString.cleanString(side));
return areExpressionEqual(sides0[0], sides1[0], equalityCache) && areExpressionEqual(sides0[1], sides1[1], equalityCache);
}
function areExpressionEqual(exp0, exp1, equalityCache = null) {
if (!exp0 || !exp1)
return false;
if (exp0 === exp1)
return true;
if (!equalityCache) {
return areExpressionEqualCore(exp0, exp1);
} else {
const strExp0 = typeof exp0 === "string" ? cleanString.cleanString(exp0) : myNodeToString.myNodeToString(exp0);
const strExp1 = typeof exp1 === "string" ? cleanString.cleanString(exp1) : myNodeToString.myNodeToString(exp1);
return equalityCache.getCachedEquality(strExp0, strExp1, areExpressionEqualCore);
}
}
function areExpressionEqualCore(exp0, exp1) {
if (!exp0 || !exp1)
return false;
if (exp0 === exp1)
return true;
const strExp0 = typeof exp0 === "string" ? cleanString.cleanString(exp0) : myNodeToString.myNodeToString(exp0);
const strExp1 = typeof exp1 === "string" ? cleanString.cleanString(exp1) : myNodeToString.myNodeToString(exp1);
if (strExp0 === strExp1)
return true;
const normalizedExprString0 = normalizeStringExpressionForEquality(strExp0);
const normalizedExprString1 = normalizeStringExpressionForEquality(strExp1);
if (normalizedExprString0 === normalizedExprString1)
return true;
if (canDoEqualityBasedOnEventualAnswer(normalizedExprString0, normalizedExprString1)) {
const answer1 = myNodeToString.myNodeToString(getNodeStepsToSolveExpression(normalizedExprString0));
const answer2 = myNodeToString.myNodeToString(getNodeStepsToSolveExpression(normalizedExprString1));
if (answer1 === answer2)
return true;
const normalizedAnswer1 = normalizeStringExpressionForEquality(answer1);
const normalizedAnswer2 = normalizeStringExpressionForEquality(answer2);
if (normalizedAnswer1 === normalizedAnswer2)
return true;
const normalizedAnswerNode0 = normalizeNodeForEquality(parseText.parseText(normalizedAnswer1));
const normalizedAnswerNode1 = normalizeNodeForEquality(parseText.parseText(normalizedAnswer2));
return normalizedAnswerNode0.equals(normalizedAnswerNode1);
} else {
const normalizedNode0 = normalizeNodeForEquality(parseText.parseText(normalizedExprString0));
const normalizedNode1 = normalizeNodeForEquality(parseText.parseText(normalizedExprString1));
return normalizedNode0.equals(normalizedNode1);
}
}
function canDoEqualityBasedOnEventualAnswer(strExp0, strExp1) {
const countMult0 = (strExp0.match(/\*/g) || []).length;
const countMult1 = (strExp1.match(/\*/g) || []).length;
if (countMult0 !== countMult1)
return false;
const countDiv0 = (strExp0.match(/\//g) || []).length;
const countDiv1 = (strExp1.match(/\//g) || []).length;
if (countDiv0 !== countDiv1)
return false;
if (strExp0.includes("/")) {
const fractions0 = strExp0.match(regex.RGFraction) || [];
const fractions1 = strExp1.match(regex.RGFraction) || [];
if (!arrayUtils.areArraysEqualUnordered(fractions0, fractions1, { isEqualFn: (a, b) => a === b }))
return false;
}
const operators = ["+", "-", "*", "/"];
operators.forEach((op) => {
strExp0 = strExp0.replaceAll(op, ` ${op} `);
strExp1 = strExp1.replaceAll(op, ` ${op} `);
});
strExp0 = strExp0.replace(/\s+/g, " ");
strExp1 = strExp1.replace(/\s+/g, " ");
strExp0 = strExp0.replaceAll("(", "").replaceAll(")", "");
strExp1 = strExp1.replaceAll("(", "").replaceAll(")", "");
strExp0 = strExp0.replaceAll("+", " ").replaceAll("-", " ");
strExp1 = strExp1.replaceAll("+", " ").replaceAll("-", " ");
const sortedStrExp0 = strExp0.split(/\s+/).sort().join("$");
const sortedStrExp1 = strExp1.split(/\s+/).sort().join("$");
return sortedStrExp0 === sortedStrExp1;
}
exports.areEquationsEqual = areEquationsEqual;
exports.areExpressionEqual = areExpressionEqual;
exports.getNodeStepsToSolveExpression = getNodeStepsToSolveExpression;
exports.normalizeNodeForEquality = normalizeNodeForEquality;
exports.normalizeStringExpressionForEquality = normalizeStringExpressionForEquality;