mathsteps-experimental-fork
Version:
Step by step math solutions. Experimental Fork
155 lines (143 loc) • 5.05 kB
JavaScript
;
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const config = require('../config.js');
const clone = require('../newServices/nodeServices/clone.js');
const index = require('../node/index.js');
const simplifyCore = require('./simplifyCore.js');
function applyRules(node, poolOfRules, options) {
let rv = null;
options = options || {};
// Possible improvement: catch many steps at once.
const steps = simplifyCore(node, poolOfRules, null, { ...options, stopOnFirstStep: true });
if (steps.length > 0) {
const oneStep = steps[0];
if (oneStep.isMistake)
oneStep.nodeAfter.isMistake = true;
rv = {
changeType: oneStep.ruleApplied.id,
rootNode: oneStep.nodeAfter,
mistakes: oneStep?.mistakes?.map(oneRes => ({ changeType: oneRes.ruleApplied.id, rootNode: oneRes.nodeAfter, isMistake: true })),
isMistake: oneStep.isMistake,
};
}
return rv
}
// Make sure we store all constant nodes as bignumber to avoid fake unequals.
function kemuNormalizeConstantNodes(node) {
if (node == null) ;
else if (node.type === 'ParenthesisNode') {
// (...) - enter into node.
node = kemuNormalizeConstantNodes(node.content);
}
else if (index.default.Type.isConstant(node)) {
// Constant node. Make sure we store value as bignumber.
node.value = config.default.bignumber(node.value);
}
else if (index.default.Type.isUnaryMinus(node) && index.default.Type.isConstant(node.args[0])) {
// Negative constant node.
// Make sure we store value as bignumber.
node = clone(node.args[0]);
node.value = config.default.multiply(config.default.bignumber(node.value), -1);
}
else if (index.default.Type.isFunction(node, 'nthRoot') && !node.args[1]) {
// nthRoot(x, null) -> nthRoot(x, 2)
node.args[0] = kemuNormalizeConstantNodes(node.args[0]);
node.args[1] = index.default.Creator.constant(2);
}
else if (index.default.Type.isFunction(node, 'log10')) {
// log10(x) -> logXY(10, x)
node.fn.name = 'logXY';
node.args[1] = kemuNormalizeConstantNodes(node.args[0]);
node.args[0] = index.default.Creator.constant(10);
}
else if (index.default.Type.isFunction(node, 'logE')) {
// logE(x) -> logXY(e, x)
node.fn.name = 'logXY';
node.args[1] = kemuNormalizeConstantNodes(node.args[0]);
node.args[0] = index.default.Creator.kemuCreateBuiltInConstant('e');
}
else {
// Non constant-node. Go on recurisively if possible.
if (node.args) {
node.args.forEach((childNode, idx) => {
node.args[idx] = kemuNormalizeConstantNodes(childNode);
});
}
}
return node
}
function _explodeNodeArgs(node, op) {
// [2x, a, b] gives [2, x, a, b]
let rv = [];
node.args.forEach((oneArg) => {
if (oneArg.op === op)
rv = rv.concat(_explodeNodeArgs(oneArg, op));
else
rv.push(oneArg);
});
return rv
}
function kemuFlatten(node, options = { keepSubtraction: false }) {
let rv = node;
if (node.args) {
// Flatten args recursively.
node.args.forEach((oneChild, idx) => {
node.args[idx] = kemuFlatten(oneChild);
});
if (index.default.Type.isOperator(node)) {
switch (node.op) {
case '*':
case '+': {
// Flatten nested multiply/add e.g. (3*x)*y =>3*x*y
node.args = _explodeNodeArgs(node, node.op);
break
}
case '-': {
if (options.keepSubtraction) {
break
}
// Convert a-b to a+(-b).
const x = node.args[0];
const y = node.args[1];
const args = index.default.Type.isOperator(x, '+') ? _explodeNodeArgs(x, '+') : [x];
const argsY = index.default.Type.isOperator(y, '+') ? _explodeNodeArgs(y, '+') : [y];
// const ogNumberOfArgs = args.length
// Possible improvement: Optimize it.
argsY.forEach((item) => {
args.push(index.default.Creator.unaryMinus(item));
});
rv = index.default.Creator.operator('+', args);
// const argsAfterOgNumberOfArgs = args.slice(ogNumberOfArgs)
// argsAfterOgNumberOfArgs.forEach((item) => {
// item.wasInitiallySubtractedBy = myNodeToString(x)
// })
break
}
}
}
}
return rv
}
/*
const deepIdx = 0
KEMU OLD
function logEnter(msg) {
if (process)
process.stdout.write(`${' '.repeat(deepIdx * 2)}-> `)
console.log.apply(console, arguments)
deepIdx++
}
function logLeave() {
deepIdx--
if (process)
process.stdout.write(`${' '.repeat(deepIdx * 2)}<- `)
console.log.apply(console, arguments)
}
function log() {
if (process)
process.stdout.write(' '.repeat(deepIdx * 2))
console.log.apply(console, arguments)
} */
exports.applyRules = applyRules;
exports.kemuFlatten = kemuFlatten;
exports.kemuNormalizeConstantNodes = kemuNormalizeConstantNodes;