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.
Files changed (90) hide show
  1. package/lib/exercises/math/calcul/arithmetics/coprime.d.ts +8 -0
  2. package/lib/exercises/math/calcul/arithmetics/coprime.d.ts.map +1 -0
  3. package/lib/exercises/math/calcul/arithmetics/coprime.js +113 -0
  4. package/lib/exercises/math/calcul/arithmetics/index.d.ts +1 -0
  5. package/lib/exercises/math/calcul/arithmetics/index.d.ts.map +1 -1
  6. package/lib/exercises/math/calcul/arithmetics/index.js +1 -0
  7. package/lib/exercises/math/calcul/decimals/decimalFractionToDecimal.d.ts +11 -0
  8. package/lib/exercises/math/calcul/decimals/decimalFractionToDecimal.d.ts.map +1 -0
  9. package/lib/exercises/math/calcul/decimals/decimalFractionToDecimal.js +243 -0
  10. package/lib/exercises/math/calcul/decimals/index.d.ts +1 -0
  11. package/lib/exercises/math/calcul/decimals/index.d.ts.map +1 -1
  12. package/lib/exercises/math/calcul/decimals/index.js +1 -0
  13. package/lib/exercises/math/calculLitteral/distributivity/doubleDistributivityAdd.d.ts +12 -0
  14. package/lib/exercises/math/calculLitteral/distributivity/doubleDistributivityAdd.d.ts.map +1 -0
  15. package/lib/exercises/math/calculLitteral/distributivity/doubleDistributivityAdd.js +173 -0
  16. package/lib/exercises/math/calculLitteral/distributivity/index.d.ts +1 -0
  17. package/lib/exercises/math/calculLitteral/distributivity/index.d.ts.map +1 -1
  18. package/lib/exercises/math/calculLitteral/distributivity/index.js +1 -0
  19. package/lib/exercises/math/calculLitteral/equation/equationSecondDegreeWithNoB.d.ts +7 -0
  20. package/lib/exercises/math/calculLitteral/equation/equationSecondDegreeWithNoB.d.ts.map +1 -0
  21. package/lib/exercises/math/calculLitteral/equation/equationSecondDegreeWithNoB.js +160 -0
  22. package/lib/exercises/math/calculLitteral/simplifying/compareMinusA.js +1 -1
  23. package/lib/exercises/math/dataRepresentations/barChartInterpreting.d.ts.map +1 -1
  24. package/lib/exercises/math/dataRepresentations/barChartInterpreting.js +0 -1
  25. package/lib/exercises/math/derivation/derivative/composition/functionCompositionDerivative.d.ts +11 -0
  26. package/lib/exercises/math/derivation/derivative/composition/functionCompositionDerivative.d.ts.map +1 -0
  27. package/lib/exercises/math/derivation/derivative/composition/functionCompositionDerivative.js +372 -0
  28. package/lib/exercises/math/derivation/derivative/composition/index.d.ts +2 -0
  29. package/lib/exercises/math/derivation/derivative/composition/index.d.ts.map +1 -0
  30. package/lib/exercises/math/derivation/derivative/composition/index.js +1 -0
  31. package/lib/exercises/math/derivation/derivative/index.d.ts +1 -0
  32. package/lib/exercises/math/derivation/derivative/index.d.ts.map +1 -1
  33. package/lib/exercises/math/derivation/derivative/index.js +1 -0
  34. package/lib/exercises/math/functions/affines/recognizeAffineGraph.d.ts.map +1 -1
  35. package/lib/exercises/math/functions/affines/recognizeAffineGraph.js +3 -3
  36. package/lib/exercises/math/functions/affines/recognizeExprAffine.js +2 -2
  37. package/lib/exercises/math/functions/composition/functionComposition.js +1 -1
  38. package/lib/exercises/math/functions/composition/functionDecompositionFindPossibleUVs.d.ts +13 -0
  39. package/lib/exercises/math/functions/composition/functionDecompositionFindPossibleUVs.d.ts.map +1 -0
  40. package/lib/exercises/math/functions/composition/functionDecompositionFindPossibleUVs.js +223 -0
  41. package/lib/exercises/math/functions/composition/functionDecompositionFindUOrV.d.ts +9 -0
  42. package/lib/exercises/math/functions/composition/functionDecompositionFindUOrV.d.ts.map +1 -0
  43. package/lib/exercises/math/functions/composition/functionDecompositionFindUOrV.js +252 -0
  44. package/lib/exercises/math/functions/composition/index.d.ts +2 -0
  45. package/lib/exercises/math/functions/composition/index.d.ts.map +1 -1
  46. package/lib/exercises/math/functions/composition/index.js +2 -0
  47. package/lib/exercises/math/geometry/cartesian/placeAbscissOnSemiLineV2.d.ts.map +1 -1
  48. package/lib/exercises/math/geometry/cartesian/placeAbscissOnSemiLineV2.js +1 -1
  49. package/lib/exercises/math/geometry/vectors/constructions/index.d.ts +1 -0
  50. package/lib/exercises/math/geometry/vectors/constructions/index.d.ts.map +1 -1
  51. package/lib/exercises/math/geometry/vectors/constructions/index.js +1 -0
  52. package/lib/exercises/math/geometry/vectors/constructions/traceVectorCL.d.ts +13 -0
  53. package/lib/exercises/math/geometry/vectors/constructions/traceVectorCL.d.ts.map +1 -0
  54. package/lib/exercises/math/geometry/vectors/constructions/traceVectorCL.js +178 -0
  55. package/lib/exercises/math/percent/evolutions/findEndValueAfterEvolution.d.ts.map +1 -1
  56. package/lib/exercises/math/percent/evolutions/findEndValueAfterEvolution.js +1 -1
  57. package/lib/exercises/math/powers/powersMixOperations.d.ts +4 -1
  58. package/lib/exercises/math/powers/powersMixOperations.d.ts.map +1 -1
  59. package/lib/exercises/math/powers/powersMixOperations.js +17 -7
  60. package/lib/exercises/math/probaStat/stats1var/plausibilityOfAverage.js +1 -1
  61. package/lib/exercises/math/sequences/geometric/geometricFindExplicitFormula.d.ts.map +1 -1
  62. package/lib/exercises/math/sequences/geometric/geometricFindExplicitFormula.js +2 -1
  63. package/lib/exercises/math/sequences/geometric/geometricFirstTermsGeneralSum.d.ts +5 -1
  64. package/lib/exercises/math/sequences/geometric/geometricFirstTermsGeneralSum.d.ts.map +1 -1
  65. package/lib/exercises/math/sequences/geometric/geometricFirstTermsGeneralSum.js +23 -6
  66. package/lib/exercises/math/sequences/recurrenceFormulaUsage.js +1 -1
  67. package/lib/index.d.ts +42 -2
  68. package/lib/index.d.ts.map +1 -1
  69. package/lib/math/utils/arithmetic/isCoprime.d.ts +2 -0
  70. package/lib/math/utils/arithmetic/isCoprime.d.ts.map +1 -0
  71. package/lib/math/utils/arithmetic/isCoprime.js +10 -0
  72. package/lib/math/utils/arithmetic/primeDecompNode.d.ts +3 -0
  73. package/lib/math/utils/arithmetic/primeDecompNode.d.ts.map +1 -0
  74. package/lib/math/utils/arithmetic/primeDecompNode.js +24 -0
  75. package/lib/math/utils/functions/functionComparison.d.ts +3 -0
  76. package/lib/math/utils/functions/functionComparison.d.ts.map +1 -0
  77. package/lib/math/utils/functions/functionComparison.js +58 -0
  78. package/lib/math/utils/functions/functionComposition.d.ts +13 -0
  79. package/lib/math/utils/functions/functionComposition.d.ts.map +1 -0
  80. package/lib/math/utils/functions/functionComposition.js +117 -0
  81. package/lib/math/utils/functions/functionDecomposition.d.ts +10 -0
  82. package/lib/math/utils/functions/functionDecomposition.d.ts.map +1 -0
  83. package/lib/math/utils/functions/functionDecomposition.js +256 -0
  84. package/lib/server.js +25 -29
  85. package/lib/tree/nodes/operators/powerNode.d.ts.map +1 -1
  86. package/lib/tree/nodes/operators/powerNode.js +4 -0
  87. package/lib/utils/strings/joinanded.d.ts +2 -0
  88. package/lib/utils/strings/joinanded.d.ts.map +1 -0
  89. package/lib/utils/strings/joinanded.js +11 -0
  90. 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
- console.log("raw", req.query.answer);
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: exo.getAnswer?.(identifiers, options) ?? "", ...identifiers }, options);
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;AAKrE,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;IAuBlC,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"}
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,2 @@
1
+ export declare const joinanded: (arrStr: string[], separator: string, lastSeparator: string) => string;
2
+ //# sourceMappingURL=joinanded.d.ts.map
@@ -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
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "math-exercises",
3
3
  "type": "module",
4
- "version": "3.0.134",
4
+ "version": "3.0.136",
5
5
  "description": "Math exercises generator for middle school and high school",
6
6
  "main": "lib/index.js",
7
7
  "files": [