mathsteps-experimental-fork
Version:
Step by step math solutions. Experimental Fork
113 lines (110 loc) • 4.82 kB
JavaScript
import { isOperatorNode, isConstantNode, ConstantNode, isSymbolNode } from '../config.js';
import { myNodeToString } from '../newServices/nodeServices/myNodeToString.js';
import { parseText } from '../newServices/nodeServices/parseText.js';
import { cleanString } from '../util/cleanString.js';
import { makeExtendedRegExp } from '../util/regex.js';
import { OperatorNode, ParenthesisNode } from '../../node_modules/.pnpm/mathjs@13.1.1/node_modules/mathjs/lib/esm/entry/impureFunctionsAny.generated.js';
function convertNumParVarDivNumToNumVarDivNum(expressionOrNode) {
const coreFn = () => {
const mathTree = typeof expressionOrNode === "string" ? parseText(expressionOrNode) : parseText(myNodeToString(expressionOrNode));
function traverse(node) {
if (isOperatorNode(node)) {
const opNode = node;
const transformedArgs = opNode.args.map(traverse);
const newNode = new OperatorNode(opNode.op, opNode.fn, transformedArgs);
if (newNode.op === "*") {
const [left, right] = newNode.args;
if (isConstantNode(left) && isOperatorNode(right) && right.op === "/") {
const rightOpNode = right;
const [numerator, denominator] = rightOpNode.args;
if (isSymbolNode(numerator) && isConstantNode(denominator)) {
const newNumerator = new OperatorNode("*", "multiply", [left, numerator]);
const newNumeratorWithParens = new ParenthesisNode(newNumerator);
const newDenominator = denominator;
const transformedNode = new OperatorNode("/", "divide", [newNumeratorWithParens, newDenominator]);
return transformedNode;
}
}
if (isOperatorNode(left) && left.op === "/" && isConstantNode(right)) {
const leftOpNode = left;
const [numerator, denominator] = leftOpNode.args;
if (isSymbolNode(numerator) && isConstantNode(denominator)) {
const newNumerator = new OperatorNode("*", "multiply", [right, numerator]);
const newNumeratorWithParens = new ParenthesisNode(newNumerator);
const newDenominator = denominator;
const transformedNode = new OperatorNode("/", "divide", [newNumeratorWithParens, newDenominator]);
return transformedNode;
}
}
}
return newNode;
} else {
return node;
}
}
return traverse(mathTree);
};
return parseText(myNodeToString(coreFn()));
}
function convertAllSimpleFractionsToDecimals(node) {
const convertFractions = (node2) => {
if (isOperatorNode(node2) && node2.op === "/" && node2.args.length === 2 && isConstantNode(node2.args[0]) && isConstantNode(node2.args[1])) {
const leftValue = node2.args[0].value;
const rightValue = node2.args[1].value;
if (leftValue % rightValue === 0) {
return node2;
}
return new ConstantNode(leftValue / rightValue);
}
if (isOperatorNode(node2) && node2.args) {
node2.args = node2.args.map(convertFractions);
}
return node2;
};
return convertFractions(node);
}
function convertAll1xToX(node) {
const convert1x = (node2) => {
if (isOperatorNode(node2) && node2.op === "*" && node2.args.length === 2 && isConstantNode(node2.args[0]) && isSymbolNode(node2.args[1]) && node2.args[0].toString() === "1") {
return node2.args[1];
}
if (isOperatorNode(node2) && node2.args) {
node2.args = node2.args.map(convert1x);
}
return node2;
};
return convert1x(node);
}
function makePlusMinusMinusAndReturnString(node) {
const nodeStr = typeof node === "string" ? cleanString(node) : myNodeToString(node);
const numberRG = "\\b\\d+(?:\\.\\d+)?[a-z]?\\b";
const regexExp = makeExtendedRegExp(
String.raw`
\+\- # +-
( # number / number match group
${numberRG}
\/
${numberRG}
)
`,
"gi"
);
return nodeStr.replace(regexExp, "+(-$1)").replaceAll("+-", "-");
}
function normalizeNegativesAndFractions(node) {
const handleNegatives = (node2) => {
if (isOperatorNode(node2) && node2.op === "/" && isConstantNode(node2.args[0]) && node2.args[0].value < 0) {
const positiveNumerator = new ConstantNode(Math.abs(node2.args[0].value));
const denominator = node2.args[1];
return new OperatorNode("-", "unaryMinus", [
new OperatorNode("/", "divide", [positiveNumerator, denominator])
]);
}
if (isOperatorNode(node2) && node2.args) {
node2.args = node2.args.map(handleNegatives);
}
return node2;
};
return handleNegatives(node);
}
export { convertAll1xToX, convertAllSimpleFractionsToDecimals, convertNumParVarDivNumToNumVarDivNum, makePlusMinusMinusAndReturnString, normalizeNegativesAndFractions };