math-exercises 3.0.134 → 3.0.136
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/exercises/math/calcul/arithmetics/coprime.d.ts +8 -0
- package/lib/exercises/math/calcul/arithmetics/coprime.d.ts.map +1 -0
- package/lib/exercises/math/calcul/arithmetics/coprime.js +113 -0
- package/lib/exercises/math/calcul/arithmetics/index.d.ts +1 -0
- package/lib/exercises/math/calcul/arithmetics/index.d.ts.map +1 -1
- package/lib/exercises/math/calcul/arithmetics/index.js +1 -0
- package/lib/exercises/math/calcul/decimals/decimalFractionToDecimal.d.ts +11 -0
- package/lib/exercises/math/calcul/decimals/decimalFractionToDecimal.d.ts.map +1 -0
- package/lib/exercises/math/calcul/decimals/decimalFractionToDecimal.js +243 -0
- package/lib/exercises/math/calcul/decimals/index.d.ts +1 -0
- package/lib/exercises/math/calcul/decimals/index.d.ts.map +1 -1
- package/lib/exercises/math/calcul/decimals/index.js +1 -0
- package/lib/exercises/math/calculLitteral/distributivity/doubleDistributivityAdd.d.ts +12 -0
- package/lib/exercises/math/calculLitteral/distributivity/doubleDistributivityAdd.d.ts.map +1 -0
- package/lib/exercises/math/calculLitteral/distributivity/doubleDistributivityAdd.js +173 -0
- package/lib/exercises/math/calculLitteral/distributivity/index.d.ts +1 -0
- package/lib/exercises/math/calculLitteral/distributivity/index.d.ts.map +1 -1
- package/lib/exercises/math/calculLitteral/distributivity/index.js +1 -0
- package/lib/exercises/math/calculLitteral/equation/equationSecondDegreeWithNoB.d.ts +7 -0
- package/lib/exercises/math/calculLitteral/equation/equationSecondDegreeWithNoB.d.ts.map +1 -0
- package/lib/exercises/math/calculLitteral/equation/equationSecondDegreeWithNoB.js +160 -0
- package/lib/exercises/math/calculLitteral/simplifying/compareMinusA.js +1 -1
- package/lib/exercises/math/dataRepresentations/barChartInterpreting.d.ts.map +1 -1
- package/lib/exercises/math/dataRepresentations/barChartInterpreting.js +0 -1
- package/lib/exercises/math/derivation/derivative/composition/functionCompositionDerivative.d.ts +11 -0
- package/lib/exercises/math/derivation/derivative/composition/functionCompositionDerivative.d.ts.map +1 -0
- package/lib/exercises/math/derivation/derivative/composition/functionCompositionDerivative.js +372 -0
- package/lib/exercises/math/derivation/derivative/composition/index.d.ts +2 -0
- package/lib/exercises/math/derivation/derivative/composition/index.d.ts.map +1 -0
- package/lib/exercises/math/derivation/derivative/composition/index.js +1 -0
- package/lib/exercises/math/derivation/derivative/index.d.ts +1 -0
- package/lib/exercises/math/derivation/derivative/index.d.ts.map +1 -1
- package/lib/exercises/math/derivation/derivative/index.js +1 -0
- package/lib/exercises/math/functions/affines/recognizeAffineGraph.d.ts.map +1 -1
- package/lib/exercises/math/functions/affines/recognizeAffineGraph.js +3 -3
- package/lib/exercises/math/functions/affines/recognizeExprAffine.js +2 -2
- package/lib/exercises/math/functions/composition/functionComposition.js +1 -1
- package/lib/exercises/math/functions/composition/functionDecompositionFindPossibleUVs.d.ts +13 -0
- package/lib/exercises/math/functions/composition/functionDecompositionFindPossibleUVs.d.ts.map +1 -0
- package/lib/exercises/math/functions/composition/functionDecompositionFindPossibleUVs.js +223 -0
- package/lib/exercises/math/functions/composition/functionDecompositionFindUOrV.d.ts +9 -0
- package/lib/exercises/math/functions/composition/functionDecompositionFindUOrV.d.ts.map +1 -0
- package/lib/exercises/math/functions/composition/functionDecompositionFindUOrV.js +252 -0
- package/lib/exercises/math/functions/composition/index.d.ts +2 -0
- package/lib/exercises/math/functions/composition/index.d.ts.map +1 -1
- package/lib/exercises/math/functions/composition/index.js +2 -0
- package/lib/exercises/math/geometry/cartesian/placeAbscissOnSemiLineV2.d.ts.map +1 -1
- package/lib/exercises/math/geometry/cartesian/placeAbscissOnSemiLineV2.js +1 -1
- package/lib/exercises/math/geometry/vectors/constructions/index.d.ts +1 -0
- package/lib/exercises/math/geometry/vectors/constructions/index.d.ts.map +1 -1
- package/lib/exercises/math/geometry/vectors/constructions/index.js +1 -0
- package/lib/exercises/math/geometry/vectors/constructions/traceVectorCL.d.ts +13 -0
- package/lib/exercises/math/geometry/vectors/constructions/traceVectorCL.d.ts.map +1 -0
- package/lib/exercises/math/geometry/vectors/constructions/traceVectorCL.js +178 -0
- package/lib/exercises/math/percent/evolutions/findEndValueAfterEvolution.d.ts.map +1 -1
- package/lib/exercises/math/percent/evolutions/findEndValueAfterEvolution.js +1 -1
- package/lib/exercises/math/powers/powersMixOperations.d.ts +4 -1
- package/lib/exercises/math/powers/powersMixOperations.d.ts.map +1 -1
- package/lib/exercises/math/powers/powersMixOperations.js +17 -7
- package/lib/exercises/math/probaStat/stats1var/plausibilityOfAverage.js +1 -1
- package/lib/exercises/math/sequences/geometric/geometricFindExplicitFormula.d.ts.map +1 -1
- package/lib/exercises/math/sequences/geometric/geometricFindExplicitFormula.js +2 -1
- package/lib/exercises/math/sequences/geometric/geometricFirstTermsGeneralSum.d.ts +5 -1
- package/lib/exercises/math/sequences/geometric/geometricFirstTermsGeneralSum.d.ts.map +1 -1
- package/lib/exercises/math/sequences/geometric/geometricFirstTermsGeneralSum.js +23 -6
- package/lib/exercises/math/sequences/recurrenceFormulaUsage.js +1 -1
- package/lib/index.d.ts +42 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/math/utils/arithmetic/isCoprime.d.ts +2 -0
- package/lib/math/utils/arithmetic/isCoprime.d.ts.map +1 -0
- package/lib/math/utils/arithmetic/isCoprime.js +10 -0
- package/lib/math/utils/arithmetic/primeDecompNode.d.ts +3 -0
- package/lib/math/utils/arithmetic/primeDecompNode.d.ts.map +1 -0
- package/lib/math/utils/arithmetic/primeDecompNode.js +24 -0
- package/lib/math/utils/functions/functionComparison.d.ts +3 -0
- package/lib/math/utils/functions/functionComparison.d.ts.map +1 -0
- package/lib/math/utils/functions/functionComparison.js +58 -0
- package/lib/math/utils/functions/functionComposition.d.ts +13 -0
- package/lib/math/utils/functions/functionComposition.d.ts.map +1 -0
- package/lib/math/utils/functions/functionComposition.js +117 -0
- package/lib/math/utils/functions/functionDecomposition.d.ts +10 -0
- package/lib/math/utils/functions/functionDecomposition.d.ts.map +1 -0
- package/lib/math/utils/functions/functionDecomposition.js +256 -0
- package/lib/server.js +25 -29
- package/lib/tree/nodes/operators/powerNode.d.ts.map +1 -1
- package/lib/tree/nodes/operators/powerNode.js +4 -0
- package/lib/utils/strings/joinanded.d.ts +2 -0
- package/lib/utils/strings/joinanded.d.ts.map +1 -0
- package/lib/utils/strings/joinanded.js +11 -0
- package/package.json +1 -1
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { isFunctionNode, } from "../../../tree/nodes/functions/functionNode.js";
|
|
2
|
+
import { NodeConstructor } from "../../../tree/nodes/nodeConstructor.js";
|
|
3
|
+
import { isOperatorNode, } from "../../../tree/nodes/operators/operatorNode.js";
|
|
4
|
+
import { isVariableNode, } from "../../../tree/nodes/variables/variableNode.js";
|
|
5
|
+
export const nodeBySubstitutingVar = (nodeCarrier, nodeInjected, variableNode = "x".toTree()) => {
|
|
6
|
+
function isTargetVariableNode(node) {
|
|
7
|
+
return isVariableNode(node) && node.name === variableNode.name;
|
|
8
|
+
}
|
|
9
|
+
const nodePathsWithVariableAtEnd = getAllNodePaths(nodeCarrier).filter((nodePathWithNodes) => isTargetVariableNode(nodePathWithNodes.arrNode[nodePathWithNodes.arrNode.length - 1]));
|
|
10
|
+
return nodePathsWithVariableAtEnd.reduce((acc, nodePathWithNodes) => nodeByReplacingNodeAtPath(acc, nodePathWithNodes.nodePath, nodeInjected), nodeCarrier);
|
|
11
|
+
};
|
|
12
|
+
export const getAllNodePaths = (node) => {
|
|
13
|
+
const arrNodePaths = [];
|
|
14
|
+
if (isOperatorNode(node)) {
|
|
15
|
+
getAllNodePaths(node.leftChild).forEach((nodePathWithNodes) => {
|
|
16
|
+
arrNodePaths.push({
|
|
17
|
+
arrNode: [node, ...nodePathWithNodes.arrNode],
|
|
18
|
+
nodePath: {
|
|
19
|
+
keys: ["leftChild", ...nodePathWithNodes.nodePath.keys],
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
getAllNodePaths(node.rightChild).forEach((nodePathWithNodes) => {
|
|
24
|
+
arrNodePaths.push({
|
|
25
|
+
arrNode: [node, ...nodePathWithNodes.arrNode],
|
|
26
|
+
nodePath: {
|
|
27
|
+
keys: ["rightChild", ...nodePathWithNodes.nodePath.keys],
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
else if (isFunctionNode(node)) {
|
|
33
|
+
getAllNodePaths(node.child).forEach((nodePathWithNodes) => {
|
|
34
|
+
arrNodePaths.push({
|
|
35
|
+
arrNode: [node, ...nodePathWithNodes.arrNode],
|
|
36
|
+
nodePath: {
|
|
37
|
+
keys: ["child", ...nodePathWithNodes.nodePath.keys],
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
arrNodePaths.push({
|
|
44
|
+
arrNode: [node],
|
|
45
|
+
nodePath: {
|
|
46
|
+
keys: [],
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return arrNodePaths;
|
|
51
|
+
};
|
|
52
|
+
function functionNodeByReplacingChild(fNode, nodeChildNew) {
|
|
53
|
+
const nodeIds = fNode.toIdentifiers();
|
|
54
|
+
nodeIds.child = nodeChildNew.toIdentifiers();
|
|
55
|
+
return NodeConstructor.fromIdentifiers(nodeIds);
|
|
56
|
+
}
|
|
57
|
+
function operatorNodeByReplacingLeftChild(opNode, nodeLeftChildNew) {
|
|
58
|
+
const nodeIds = opNode.toIdentifiers();
|
|
59
|
+
nodeIds.leftChild = nodeLeftChildNew.toIdentifiers();
|
|
60
|
+
return NodeConstructor.fromIdentifiers(nodeIds);
|
|
61
|
+
}
|
|
62
|
+
function operatorNodeByReplacingRightChild(opNode, nodeRightChildNew) {
|
|
63
|
+
const nodeIds = opNode.toIdentifiers();
|
|
64
|
+
nodeIds.rightChild = nodeRightChildNew.toIdentifiers();
|
|
65
|
+
return NodeConstructor.fromIdentifiers(nodeIds);
|
|
66
|
+
}
|
|
67
|
+
export function nodeByReplacingNodeAtPath(nodeCarrier, path, nodeInjected, simplifyUpToLevel = -1, simplifyOptions = {}) {
|
|
68
|
+
// console.log("nodeByReplacingNodeAtPath", {
|
|
69
|
+
// node: nodeCarrier.toTex(),
|
|
70
|
+
// key: path.keys.join("."),
|
|
71
|
+
// nodeInjected: nodeInjected.toTex(),
|
|
72
|
+
// });
|
|
73
|
+
function getNodeForKey(node, key) {
|
|
74
|
+
if (key === "leftChild" || key === "rightChild") {
|
|
75
|
+
return node[key];
|
|
76
|
+
}
|
|
77
|
+
else if (key === "child") {
|
|
78
|
+
return node[key];
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
throw new Error("Unsupported key in path.keys: " + key);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function nodeByReplacingChildAtKey(node, key, nodeInjected) {
|
|
85
|
+
// console.log("nodeByReplacingChildAtKey", {
|
|
86
|
+
// node: node.toTex(),
|
|
87
|
+
// key: key,
|
|
88
|
+
// nodeInjected: nodeInjected.toTex(),
|
|
89
|
+
// });
|
|
90
|
+
if (key === "leftChild" && isOperatorNode(node)) {
|
|
91
|
+
return operatorNodeByReplacingLeftChild(node, nodeInjected);
|
|
92
|
+
}
|
|
93
|
+
else if (key === "rightChild" && isOperatorNode(node)) {
|
|
94
|
+
return operatorNodeByReplacingRightChild(node, nodeInjected);
|
|
95
|
+
}
|
|
96
|
+
else if (key === "child" && isFunctionNode(node)) {
|
|
97
|
+
return functionNodeByReplacingChild(node, nodeInjected);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
throw new Error("Either key and node type are incompatible or Unsupported key: " + key);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const arrNodeReversed = path.keys
|
|
104
|
+
.slice(0, -1)
|
|
105
|
+
.reduce((acc, key) => {
|
|
106
|
+
return [...acc, getNodeForKey(acc[acc.length - 1], key)];
|
|
107
|
+
}, [nodeCarrier])
|
|
108
|
+
.toReversed();
|
|
109
|
+
return path.keys.toReversed().reduce((acc, key, i) => {
|
|
110
|
+
const carrierNode = arrNodeReversed[i];
|
|
111
|
+
let nodeReplacement = nodeByReplacingChildAtKey(carrierNode, key, acc);
|
|
112
|
+
if (i <= simplifyUpToLevel) {
|
|
113
|
+
nodeReplacement = nodeReplacement.simplify(simplifyOptions);
|
|
114
|
+
}
|
|
115
|
+
return nodeReplacement;
|
|
116
|
+
}, nodeInjected);
|
|
117
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { AlgebraicNode } from "../../../tree/nodes/algebraicNode.js";
|
|
2
|
+
import { VariableNode } from "../../../tree/nodes/variables/variableNode.js";
|
|
3
|
+
export declare const functionDecompositions: (node: AlgebraicNode, variableNode?: VariableNode) => {
|
|
4
|
+
nodeU: AlgebraicNode;
|
|
5
|
+
nodeV: AlgebraicNode;
|
|
6
|
+
}[];
|
|
7
|
+
export declare const nodeBySubstitutingX: (node: AlgebraicNode, strVar: string) => AlgebraicNode;
|
|
8
|
+
export declare function composeNodes(nodeU: AlgebraicNode, nodeV: AlgebraicNode): AlgebraicNode;
|
|
9
|
+
export declare function isContainingFacetiousFrac(node: AlgebraicNode): boolean;
|
|
10
|
+
//# sourceMappingURL=functionDecomposition.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"functionDecomposition.d.ts","sourceRoot":"","sources":["../../../../src/math/utils/functions/functionDecomposition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAYlE,OAAO,EAEL,YAAY,EACb,MAAM,4CAA4C,CAAC;AAcpD,eAAO,MAAM,sBAAsB,GACjC,MAAM,aAAa,EACnB,eAAc,YAA2C;WAElC,aAAa;WAAS,aAAa;GA8Q3D,CAAC;AAwEF,eAAO,MAAM,mBAAmB,GAAI,MAAM,aAAa,EAAE,QAAQ,MAAM,kBAItE,CAAC;AAEF,wBAAgB,YAAY,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,iBAMtE;AAMD,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAmBtE"}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { abs } from "../../../tree/nodes/functions/absNode.js";
|
|
2
|
+
import { isFunctionNode } from "../../../tree/nodes/functions/functionNode.js";
|
|
3
|
+
import { isNumberNode } from "../../../tree/nodes/numbers/numberNode.js";
|
|
4
|
+
import { add } from "../../../tree/nodes/operators/addNode.js";
|
|
5
|
+
import { frac, isFractionNode, } from "../../../tree/nodes/operators/fractionNode.js";
|
|
6
|
+
import { multiply } from "../../../tree/nodes/operators/multiplyNode.js";
|
|
7
|
+
import { isOperatorNode } from "../../../tree/nodes/operators/operatorNode.js";
|
|
8
|
+
import { substract } from "../../../tree/nodes/operators/substractNode.js";
|
|
9
|
+
import { isVariableNode, } from "../../../tree/nodes/variables/variableNode.js";
|
|
10
|
+
import { parseAlgebraic } from "../../../tree/parsers/latexParser.js";
|
|
11
|
+
import { randomMany } from "../../../utils/alea/random.js";
|
|
12
|
+
import { getCartesiansProducts } from "../../../utils/arrays/cartesianProducts.js";
|
|
13
|
+
import { getAllNodePaths, nodeByReplacingNodeAtPath, } from "./functionComposition.js";
|
|
14
|
+
//
|
|
15
|
+
// Function decompositions: get all (u,v) so that f = uov
|
|
16
|
+
//
|
|
17
|
+
export const functionDecompositions = (node, variableNode = "x".toTree()) => {
|
|
18
|
+
const outArr = [];
|
|
19
|
+
function isTargetVariableNode(node) {
|
|
20
|
+
return isVariableNode(node) && node.name === variableNode.name;
|
|
21
|
+
}
|
|
22
|
+
const nodePathsWithVariableAtEnd = getAllNodePaths(node).filter((nodePathWithNodes) => isTargetVariableNode(nodePathWithNodes.arrNode[nodePathWithNodes.arrNode.length - 1]));
|
|
23
|
+
function nodePathUpward(nodePathWithNodes, level) {
|
|
24
|
+
return {
|
|
25
|
+
arrNode: nodePathWithNodes.arrNode.slice(0, nodePathWithNodes.arrNode.length - level),
|
|
26
|
+
nodePath: {
|
|
27
|
+
keys: nodePathWithNodes.nodePath.keys.slice(0, nodePathWithNodes.nodePath.keys.length - level),
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function isNodesAreSame(node1, node2) {
|
|
32
|
+
const value = substract(node1, node2)
|
|
33
|
+
.simplify()
|
|
34
|
+
.evaluate({ [variableNode.name]: 177 });
|
|
35
|
+
return value === 0;
|
|
36
|
+
}
|
|
37
|
+
function isValidNodeU(nodeU) {
|
|
38
|
+
return (!isContainingFacetiousFrac(nodeU) &&
|
|
39
|
+
!nodeU.toTex().includes("NaN") &&
|
|
40
|
+
outArr.every(({ nodeU: nodeUExisting }) => !isNodesAreSame(nodeU, nodeUExisting)));
|
|
41
|
+
}
|
|
42
|
+
let counter = 0;
|
|
43
|
+
const levelPicks = getCartesiansProducts(nodePathsWithVariableAtEnd.map((nodePathWithNodes) => [
|
|
44
|
+
...Array(nodePathWithNodes.nodePath.keys.length).keys(),
|
|
45
|
+
]));
|
|
46
|
+
// console.log("levelPicks", levelPicks.length);
|
|
47
|
+
levelPicks.forEach((levelPick) => {
|
|
48
|
+
if (counter > 1000) {
|
|
49
|
+
return outArr;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const nodePathsUpByLevel = nodePathsWithVariableAtEnd.map((nodePathWithNodes, i) => {
|
|
53
|
+
const level = levelPick[i];
|
|
54
|
+
return nodePathUpward(nodePathWithNodes, level);
|
|
55
|
+
});
|
|
56
|
+
// console.log(
|
|
57
|
+
// "nodePathsUpByLevel",
|
|
58
|
+
// nodePathsUpByLevel.map((nodePathWithNodes) => {
|
|
59
|
+
// return {
|
|
60
|
+
// endNode:
|
|
61
|
+
// nodePathWithNodes.arrNode[
|
|
62
|
+
// nodePathWithNodes.arrNode.length - 1
|
|
63
|
+
// ].toTex(),
|
|
64
|
+
// keypath: nodePathWithNodes.nodePath.keys.join("."),
|
|
65
|
+
// };
|
|
66
|
+
// }),
|
|
67
|
+
// );
|
|
68
|
+
//merge wrt collision (collision means that some of the wrappedVariables trees are superimposing, and we don't want that)
|
|
69
|
+
const mergedNodePathsUpByLevel = nodePathsUpByLevel.reduce((acc, incomingNodePathWithNodes) => {
|
|
70
|
+
const incomingNodePathsString = incomingNodePathWithNodes.nodePath.keys.join(".");
|
|
71
|
+
const isIncomingIncluded = acc.some((accumulatedNodePathWithNodes) => {
|
|
72
|
+
const accumulatedNodePathsString = accumulatedNodePathWithNodes.nodePath.keys.join(".");
|
|
73
|
+
return incomingNodePathsString.startsWith(accumulatedNodePathsString);
|
|
74
|
+
});
|
|
75
|
+
const nodesPathsNotIncludedByIncoming = acc.filter((accumulatedNodePathWithNodes) => {
|
|
76
|
+
const accumulatedNodePathsString = accumulatedNodePathWithNodes.nodePath.keys.join(".");
|
|
77
|
+
return !accumulatedNodePathsString.startsWith(incomingNodePathsString);
|
|
78
|
+
});
|
|
79
|
+
if (isIncomingIncluded) {
|
|
80
|
+
return acc;
|
|
81
|
+
}
|
|
82
|
+
else if (nodesPathsNotIncludedByIncoming.length !== acc.length) {
|
|
83
|
+
return [
|
|
84
|
+
...nodesPathsNotIncludedByIncoming,
|
|
85
|
+
incomingNodePathWithNodes,
|
|
86
|
+
];
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
return [...acc, incomingNodePathWithNodes];
|
|
90
|
+
}
|
|
91
|
+
}, []);
|
|
92
|
+
// console.log(
|
|
93
|
+
// "mergedNodePathsUpByLevel",
|
|
94
|
+
// mergedNodePathsUpByLevel.map((nodePathWithNodes) => {
|
|
95
|
+
// return {
|
|
96
|
+
// endNode:
|
|
97
|
+
// nodePathWithNodes.arrNode[
|
|
98
|
+
// nodePathWithNodes.arrNode.length - 1
|
|
99
|
+
// ].toTex(),
|
|
100
|
+
// keypath: nodePathWithNodes.nodePath.keys.join("."),
|
|
101
|
+
// };
|
|
102
|
+
// }),
|
|
103
|
+
// );
|
|
104
|
+
const wrappedVariables = mergedNodePathsUpByLevel.map((nodePathWithNodes) => nodePathWithNodes &&
|
|
105
|
+
nodePathWithNodes.arrNode[nodePathWithNodes.arrNode.length - 1]);
|
|
106
|
+
for (let index = 0; index < wrappedVariables.length; index++) {
|
|
107
|
+
const sameNodeCandidate = wrappedVariables[index];
|
|
108
|
+
const otherWrappedVariables = wrappedVariables.filter((_, i) => i !== index);
|
|
109
|
+
const isSameNode = otherWrappedVariables.every((node) => isNodesAreSame(node, sameNodeCandidate));
|
|
110
|
+
if (isSameNode) {
|
|
111
|
+
const sameNode = sameNodeCandidate;
|
|
112
|
+
//replaces all sameNode with variableNode
|
|
113
|
+
const nodeU = mergedNodePathsUpByLevel.reduce((acc, nodePathWithNodes) => nodeByReplacingNodeAtPath(acc, nodePathWithNodes.nodePath, variableNode), node);
|
|
114
|
+
if (isValidNodeU(nodeU)) {
|
|
115
|
+
const nodeV = sameNode;
|
|
116
|
+
outArr.push({ nodeU, nodeV });
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
//attempt salvation
|
|
121
|
+
const comparisonDicts = otherWrappedVariables.map((node) => getComparisonDict(node, sameNodeCandidate));
|
|
122
|
+
// console.log(
|
|
123
|
+
// "comparisonDicts",
|
|
124
|
+
// comparisonDicts.map((comparisonDict) => {
|
|
125
|
+
// return {
|
|
126
|
+
// sub: comparisonDict?.sub?.toTex(),
|
|
127
|
+
// frac: comparisonDict?.frac?.toTex(),
|
|
128
|
+
// };
|
|
129
|
+
// }),
|
|
130
|
+
// );
|
|
131
|
+
const isSalvationPossible = comparisonDicts.every((comparisonDict) => comparisonDict?.sub !== undefined ||
|
|
132
|
+
comparisonDict?.frac !== undefined);
|
|
133
|
+
if (isSalvationPossible) {
|
|
134
|
+
const nodeGaskets = comparisonDicts.map((comparisonDict) => {
|
|
135
|
+
if (comparisonDict.sub !== undefined) {
|
|
136
|
+
return add(variableNode, comparisonDict.sub);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
return multiply(comparisonDict.frac, variableNode);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
// console.log(
|
|
143
|
+
// "nodeGaskets",
|
|
144
|
+
// nodeGaskets.map((node) => node.toTex()),
|
|
145
|
+
// );
|
|
146
|
+
const nodeUEnds = [...Array(wrappedVariables.length).keys()].map((i) => {
|
|
147
|
+
if (i === index) {
|
|
148
|
+
return variableNode;
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
return nodeGaskets[i < index ? i : i - 1];
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
let nodeU;
|
|
155
|
+
try {
|
|
156
|
+
nodeU = mergedNodePathsUpByLevel.reduce((acc, nodePathWithNodes, i) => nodeByReplacingNodeAtPath(acc, nodePathWithNodes.nodePath, nodeUEnds[i], 1, {}), node);
|
|
157
|
+
}
|
|
158
|
+
catch (_) {
|
|
159
|
+
try {
|
|
160
|
+
nodeU = mergedNodePathsUpByLevel.reduce((acc, nodePathWithNodes, i) => nodeByReplacingNodeAtPath(acc, nodePathWithNodes.nodePath, nodeUEnds[i], 0, {}), node);
|
|
161
|
+
}
|
|
162
|
+
catch (_) {
|
|
163
|
+
nodeU = mergedNodePathsUpByLevel.reduce((acc, nodePathWithNodes, i) => nodeByReplacingNodeAtPath(acc, nodePathWithNodes.nodePath, nodeUEnds[i]), node);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (isValidNodeU(nodeU)) {
|
|
167
|
+
const nodeV = sameNodeCandidate;
|
|
168
|
+
outArr.push({ nodeU, nodeV });
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
counter++;
|
|
175
|
+
});
|
|
176
|
+
return outArr;
|
|
177
|
+
};
|
|
178
|
+
//
|
|
179
|
+
// Function comparison
|
|
180
|
+
//
|
|
181
|
+
function getComparisonDict(node1, node2) {
|
|
182
|
+
const pool = [...Array(1000).keys()].map((i) => i - 500);
|
|
183
|
+
const evals = randomMany(pool, 5).map((x) => {
|
|
184
|
+
let v1;
|
|
185
|
+
try {
|
|
186
|
+
v1 = node1.evaluate({ x });
|
|
187
|
+
}
|
|
188
|
+
catch (_) {
|
|
189
|
+
v1 = undefined;
|
|
190
|
+
}
|
|
191
|
+
let v2;
|
|
192
|
+
try {
|
|
193
|
+
v2 = node2.evaluate({ x });
|
|
194
|
+
}
|
|
195
|
+
catch (_) {
|
|
196
|
+
v2 = undefined;
|
|
197
|
+
}
|
|
198
|
+
return { v1, v2 };
|
|
199
|
+
});
|
|
200
|
+
const successfulEvals = evals.filter(({ v1, v2 }) => v1 !== undefined && v2 !== undefined);
|
|
201
|
+
if (successfulEvals.length > 4) {
|
|
202
|
+
return {
|
|
203
|
+
sub: successfulEvals
|
|
204
|
+
.slice(1)
|
|
205
|
+
.every(({ v1, v2 }) => v1 - v2 === successfulEvals[0].v1 - successfulEvals[0].v2)
|
|
206
|
+
? substract(successfulEvals[0].v1, successfulEvals[0].v2).simplify()
|
|
207
|
+
: undefined,
|
|
208
|
+
frac: (() => {
|
|
209
|
+
const successfulEvalsWithoutZeroV2 = successfulEvals.filter(({ v2 }) => v2 !== 0);
|
|
210
|
+
// console.log(
|
|
211
|
+
// "successfulEvalsWithoutZeroV2",
|
|
212
|
+
// successfulEvalsWithoutZeroV2,
|
|
213
|
+
// );
|
|
214
|
+
return successfulEvalsWithoutZeroV2
|
|
215
|
+
.slice(1)
|
|
216
|
+
.every(({ v1, v2 }) => substract(frac(v1, v2), frac(successfulEvalsWithoutZeroV2[0].v1, successfulEvalsWithoutZeroV2[0].v2)).evaluate() === 0)
|
|
217
|
+
? frac(successfulEvalsWithoutZeroV2[0].v1, successfulEvalsWithoutZeroV2[0].v2).simplify({ towardsDistribute: true })
|
|
218
|
+
: undefined;
|
|
219
|
+
})(),
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
return undefined;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
//
|
|
227
|
+
// Function composition
|
|
228
|
+
//
|
|
229
|
+
export const nodeBySubstitutingX = (node, strVar) => {
|
|
230
|
+
return parseAlgebraic(node.toTex({ forceParenthesis: true }).replaceAll("x", `("${strVar}")`));
|
|
231
|
+
};
|
|
232
|
+
export function composeNodes(nodeU, nodeV) {
|
|
233
|
+
const nodeUOV = nodeBySubstitutingX(nodeU.simplify(), nodeV.simplify().toTex()).simplify();
|
|
234
|
+
return nodeUOV;
|
|
235
|
+
}
|
|
236
|
+
//
|
|
237
|
+
// facetious fracs
|
|
238
|
+
//
|
|
239
|
+
export function isContainingFacetiousFrac(node) {
|
|
240
|
+
if (isOperatorNode(node)) {
|
|
241
|
+
if (isFractionNode(node)) {
|
|
242
|
+
return [node.leftChild, node.rightChild].every((nodeChild) => isNumberNode(nodeChild) &&
|
|
243
|
+
abs(nodeChild).evaluate() > Math.pow(10, 10));
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
return (isContainingFacetiousFrac(node.leftChild) ||
|
|
247
|
+
isContainingFacetiousFrac(node.rightChild));
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
else if (isFunctionNode(node)) {
|
|
251
|
+
return isContainingFacetiousFrac(node.child);
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
}
|
package/lib/server.js
CHANGED
|
@@ -30,6 +30,7 @@ const runServer = () => {
|
|
|
30
30
|
console.log("math exos", mathExercises.length);
|
|
31
31
|
console.log("math hints", mathExercises.filter((exo) => exo.hasHintAndCorrection).length);
|
|
32
32
|
console.log("pc exos", `${pcExercises.length}`);
|
|
33
|
+
console.log("pc hints", pcExercises.filter((exo) => exo.hasHintAndCorrection).length);
|
|
33
34
|
playground();
|
|
34
35
|
logIdentifiers();
|
|
35
36
|
app.get("/", (_req, res) => {
|
|
@@ -45,7 +46,7 @@ const runServer = () => {
|
|
|
45
46
|
const n = Number(req.query.n);
|
|
46
47
|
const exoId = req.query.exoId;
|
|
47
48
|
const options = req.query.options
|
|
48
|
-
? JSON.parse(req.query.options)
|
|
49
|
+
? JSON.parse(decodeURIComponent(req.query.options))
|
|
49
50
|
: undefined;
|
|
50
51
|
const exo = allExercises.find((exo) => exo.id == exoId);
|
|
51
52
|
if (!exo) {
|
|
@@ -63,10 +64,10 @@ const runServer = () => {
|
|
|
63
64
|
return;
|
|
64
65
|
}
|
|
65
66
|
const identifiers = req.query.identifiers
|
|
66
|
-
? JSON.parse(req.query.identifiers)
|
|
67
|
+
? JSON.parse(decodeURIComponent(req.query.identifiers))
|
|
67
68
|
: undefined;
|
|
68
69
|
const options = req.query.options
|
|
69
|
-
? JSON.parse(req.query.options)
|
|
70
|
+
? JSON.parse(decodeURIComponent(req.query.options))
|
|
70
71
|
: undefined;
|
|
71
72
|
const question = exo?.getQuestionFromIdentifiers(identifiers, options);
|
|
72
73
|
res.json({
|
|
@@ -78,16 +79,13 @@ const runServer = () => {
|
|
|
78
79
|
const n = Number(req.query.n) || 4;
|
|
79
80
|
const exoId = req.query.exoId;
|
|
80
81
|
const options = req.query.options
|
|
81
|
-
? JSON.parse(req.query.options)
|
|
82
|
+
? JSON.parse(decodeURIComponent(req.query.options))
|
|
82
83
|
: undefined;
|
|
83
84
|
const identifiers = req.query.identifiers
|
|
84
|
-
? JSON.parse(req.query.identifiers)
|
|
85
|
+
? JSON.parse(decodeURIComponent(req.query.identifiers))
|
|
85
86
|
: undefined;
|
|
86
|
-
|
|
87
|
-
console.log("dec", decodeURI(req.query.answer));
|
|
88
|
-
const answer = JSON.parse(decodeURI(req.query.answer));
|
|
87
|
+
const answer = JSON.parse(decodeURIComponent(req.query.answer));
|
|
89
88
|
const exo = allExercises.find((exo) => exo.id == exoId);
|
|
90
|
-
console.log("ans", answer);
|
|
91
89
|
if (!exo) {
|
|
92
90
|
res.send("Exo not found");
|
|
93
91
|
return;
|
|
@@ -96,19 +94,19 @@ const runServer = () => {
|
|
|
96
94
|
res.send("no getPropositions");
|
|
97
95
|
return;
|
|
98
96
|
}
|
|
99
|
-
const props = exo.getPropositions(n, { answer
|
|
97
|
+
const props = exo.getPropositions(n, { answer, ...identifiers }, options);
|
|
100
98
|
res.json(props);
|
|
101
99
|
});
|
|
102
100
|
app.get("/isAnswerTableValid", (req, res) => {
|
|
103
101
|
const exoId = req.query.exoId;
|
|
104
102
|
const options = req.query.options
|
|
105
|
-
? JSON.parse(req.query.options)
|
|
103
|
+
? JSON.parse(decodeURIComponent(req.query.options))
|
|
106
104
|
: undefined;
|
|
107
105
|
const identifiers = req.query.identifiers
|
|
108
|
-
? JSON.parse(req.query.identifiers)
|
|
106
|
+
? JSON.parse(decodeURIComponent(req.query.identifiers))
|
|
109
107
|
: undefined;
|
|
110
|
-
const studentAnswer = JSON.parse(req.query.studentAnswer);
|
|
111
|
-
const answerTable = JSON.parse(req.query.answerTable);
|
|
108
|
+
const studentAnswer = JSON.parse(decodeURIComponent(req.query.studentAnswer));
|
|
109
|
+
const answerTable = JSON.parse(decodeURIComponent(req.query.answerTable));
|
|
112
110
|
const exo = allExercises.find((exo) => exo.id == exoId);
|
|
113
111
|
if (!exo) {
|
|
114
112
|
res.send("Exo not found");
|
|
@@ -124,13 +122,13 @@ const runServer = () => {
|
|
|
124
122
|
app.get("/isAnswerValid", (req, res) => {
|
|
125
123
|
const exoId = req.query.exoId;
|
|
126
124
|
const options = req.query.options
|
|
127
|
-
? JSON.parse(req.query.options)
|
|
125
|
+
? JSON.parse(decodeURIComponent(req.query.options))
|
|
128
126
|
: undefined;
|
|
129
127
|
const identifiers = req.query.identifiers
|
|
130
|
-
? JSON.parse(req.query.identifiers)
|
|
128
|
+
? JSON.parse(decodeURIComponent(req.query.identifiers))
|
|
131
129
|
: undefined;
|
|
132
|
-
const studentAnswer = JSON.parse(req.query.studentAnswer);
|
|
133
|
-
const answer = JSON.parse(req.query.answer);
|
|
130
|
+
const studentAnswer = JSON.parse(decodeURIComponent(req.query.studentAnswer));
|
|
131
|
+
const answer = JSON.parse(decodeURIComponent(req.query.answer));
|
|
134
132
|
const exo = allExercises.find((exo) => exo.id == exoId);
|
|
135
133
|
if (!exo) {
|
|
136
134
|
res.send("Exo not found");
|
|
@@ -140,21 +138,19 @@ const runServer = () => {
|
|
|
140
138
|
res.send("no isAnswerValid");
|
|
141
139
|
return;
|
|
142
140
|
}
|
|
143
|
-
console.log("there");
|
|
144
141
|
const valid = exo.isAnswerValid(studentAnswer, { answer, ...identifiers }, options);
|
|
145
|
-
console.log(valid);
|
|
146
142
|
res.json(valid);
|
|
147
143
|
});
|
|
148
144
|
app.get("/isGGBAnswerValid", (req, res) => {
|
|
149
145
|
const exoId = req.query.exoId;
|
|
150
146
|
const options = req.query.options
|
|
151
|
-
? JSON.parse(req.query.options)
|
|
147
|
+
? JSON.parse(decodeURIComponent(req.query.options))
|
|
152
148
|
: undefined;
|
|
153
149
|
const identifiers = req.query.identifiers
|
|
154
|
-
? JSON.parse(req.query.identifiers)
|
|
150
|
+
? JSON.parse(decodeURIComponent(req.query.identifiers))
|
|
155
151
|
: undefined;
|
|
156
|
-
const studentAnswer = JSON.parse(req.query.studentAnswer);
|
|
157
|
-
const ggbAnswer = JSON.parse(req.query.ggbAnswer);
|
|
152
|
+
const studentAnswer = JSON.parse(decodeURIComponent(req.query.studentAnswer));
|
|
153
|
+
const ggbAnswer = JSON.parse(decodeURIComponent(req.query.ggbAnswer));
|
|
158
154
|
const exo = allExercises.find((exo) => exo.id == exoId);
|
|
159
155
|
if (!exo) {
|
|
160
156
|
res.send("Exo not found");
|
|
@@ -170,7 +166,7 @@ const runServer = () => {
|
|
|
170
166
|
app.get("/question", (req, res) => {
|
|
171
167
|
const exoId = req.query.exoId;
|
|
172
168
|
const options = req.query.options
|
|
173
|
-
? JSON.parse(req.query.options)
|
|
169
|
+
? JSON.parse(decodeURIComponent(req.query.options))
|
|
174
170
|
: undefined;
|
|
175
171
|
const exoIndex = allExercises.findIndex((exo) => exo.id == exoId);
|
|
176
172
|
const exo = allExercises[exoIndex];
|
|
@@ -185,7 +181,7 @@ const runServer = () => {
|
|
|
185
181
|
app.get("/exo", (req, res) => {
|
|
186
182
|
const exoId = req.query.exoId;
|
|
187
183
|
const options = req.query.options
|
|
188
|
-
? JSON.parse(req.query.options)
|
|
184
|
+
? JSON.parse(decodeURIComponent(req.query.options))
|
|
189
185
|
: undefined;
|
|
190
186
|
const exoIndex = allExercises.findIndex((exo) => exo.id == exoId);
|
|
191
187
|
const exo = allExercises[exoIndex];
|
|
@@ -203,7 +199,7 @@ const runServer = () => {
|
|
|
203
199
|
app.get("/qcmExo", (req, res) => {
|
|
204
200
|
const exoId = req.query.exoId;
|
|
205
201
|
const options = req.query.options
|
|
206
|
-
? JSON.parse(req.query.options)
|
|
202
|
+
? JSON.parse(decodeURIComponent(req.query.options))
|
|
207
203
|
: undefined;
|
|
208
204
|
const exoIndex = allExercises.findIndex((exo) => exo.id == exoId);
|
|
209
205
|
const exo = allExercises[exoIndex];
|
|
@@ -230,7 +226,7 @@ const runServer = () => {
|
|
|
230
226
|
app.post("/vea", jsonParser, (req, res) => {
|
|
231
227
|
const exoId = req.query.exoId;
|
|
232
228
|
const options = req.query.options
|
|
233
|
-
? JSON.parse(req.query.options)
|
|
229
|
+
? JSON.parse(decodeURIComponent(req.query.options))
|
|
234
230
|
: undefined;
|
|
235
231
|
const { ans, veaProps } = req.body;
|
|
236
232
|
const exoIndex = allExercises.findIndex((exo) => exo.id == exoId);
|
|
@@ -251,7 +247,7 @@ const runServer = () => {
|
|
|
251
247
|
app.post("/tableVea", jsonParser, (req, res) => {
|
|
252
248
|
const exoId = req.query.exoId;
|
|
253
249
|
const options = req.query.options
|
|
254
|
-
? JSON.parse(req.query.options)
|
|
250
|
+
? JSON.parse(decodeURIComponent(req.query.options))
|
|
255
251
|
: undefined;
|
|
256
252
|
const { ans, veaProps } = req.body;
|
|
257
253
|
const exoIndex = allExercises.findIndex((exo) => exo.id == exoId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"powerNode.d.ts","sourceRoot":"","sources":["../../../../src/tree/nodes/operators/powerNode.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,YAAY,EAAkB,MAAM,mBAAmB,CAAC;AAG9E,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"powerNode.d.ts","sourceRoot":"","sources":["../../../../src/tree/nodes/operators/powerNode.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,YAAY,EAAkB,MAAM,mBAAmB,CAAC;AAG9E,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAMrE,wBAAgB,WAAW,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,IAAI,SAAS,CAEnD;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,IAAI,UAAU,CAErD;AACD,eAAO,MAAM,MAAM,GAAI,GAAG,aAAa,GAAG,MAAM,GAAG,MAAM,eAKxD,CAAC;AAEF,eAAO,MAAM,KAAK,GAChB,GAAG,aAAa,GAAG,MAAM,GAAG,MAAM,EAClC,GAAG,aAAa,GAAG,MAAM,GAAG,MAAM,EAClC,OAAO,WAAW,cAOnB,CAAC;AAEF,qBAAa,SAAU,YAAW,YAAY;IAC5C,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,EAAE,EAAE,WAAW,CAAC;IAChB,SAAS,EAAE,aAAa,CAAC;IACzB,UAAU,EAAE,aAAa,CAAC;IAC1B,IAAI,EAAE,QAAQ,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;gBAEjB,SAAS,EAAE,aAAa,EACxB,UAAU,EAAE,aAAa,EACzB,IAAI,CAAC,EAAE,WAAW;IAUpB,YAAY,IAAI,MAAM;IAGtB,aAAa;;;;;;;;;IAOb,iBAAiB;IAqBjB,cAAc,IAAI,MAAM,EAAE;IAI1B,KAAK,CAAC,IAAI,CAAC,EAAE,YAAY,GAAG,MAAM;IA0BlC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAMtC,oBAAoB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC;IAOxD,QAAQ,CAAC,IAAI,CAAC,EAAE,eAAe,EAAE,IAAI,UAAQ,GAAG,aAAa;IA6D7D,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO;IAOpC,UAAU,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,aAAa;CAcxD;AAED,qBAAa,UAAW,SAAQ,SAAS;gBAC3B,KAAK,EAAE,aAAa,EAAE,IAAI,CAAC,EAAE,WAAW;CAIrD"}
|
|
@@ -6,6 +6,7 @@ import { MultiplyNode, isMultiplyNode, multiply } from "./multiplyNode.js";
|
|
|
6
6
|
import { isSqrtNode } from "../functions/sqrtNode.js";
|
|
7
7
|
import { round } from "../../../math/utils/round.js";
|
|
8
8
|
import { FractionNode, isFractionNode } from "./fractionNode.js";
|
|
9
|
+
import { FunctionsIds, isFunctionNode } from "../functions/functionNode.js";
|
|
9
10
|
export function isPowerNode(a) {
|
|
10
11
|
return isOperatorNode(a) && a.id === OperatorIds.power;
|
|
11
12
|
}
|
|
@@ -84,6 +85,9 @@ export class PowerNode {
|
|
|
84
85
|
OperatorIds.power,
|
|
85
86
|
].includes(this.leftChild.id);
|
|
86
87
|
}
|
|
88
|
+
if (isFunctionNode(this.leftChild)) {
|
|
89
|
+
needBrackets ||= [FunctionsIds.exp].includes(this.leftChild.id);
|
|
90
|
+
}
|
|
87
91
|
if (needBrackets)
|
|
88
92
|
leftTex = `\\left(${leftTex}\\right)`;
|
|
89
93
|
const needBrace = rightTex.length > 1;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"joinanded.d.ts","sourceRoot":"","sources":["../../../src/utils/strings/joinanded.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,GACpB,QAAQ,MAAM,EAAE,EAChB,WAAW,MAAM,EACjB,eAAe,MAAM,WAWtB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const joinanded = (arrStr, separator, lastSeparator) => {
|
|
2
|
+
if (arrStr.length === 0) {
|
|
3
|
+
return "";
|
|
4
|
+
}
|
|
5
|
+
else if (arrStr.length === 1) {
|
|
6
|
+
return arrStr[0];
|
|
7
|
+
}
|
|
8
|
+
else {
|
|
9
|
+
return `${arrStr.slice(0, -1).join(separator)}${lastSeparator}${arrStr[arrStr.length - 1]}`;
|
|
10
|
+
}
|
|
11
|
+
};
|