math-exercises 3.0.198 → 3.0.200
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/exercise.d.ts +14 -1
- package/lib/exercises/exercise.d.ts.map +1 -1
- package/lib/exercises/math/_debug/debugReorder1.d.ts +8 -0
- package/lib/exercises/math/_debug/debugReorder1.d.ts.map +1 -0
- package/lib/exercises/math/_debug/debugReorder1.js +81 -0
- package/lib/exercises/math/_debug/debugReorder2.d.ts +10 -0
- package/lib/exercises/math/_debug/debugReorder2.d.ts.map +1 -0
- package/lib/exercises/math/_debug/debugReorder2.js +88 -0
- package/lib/exercises/math/_debug/debugReorder3.d.ts +10 -0
- package/lib/exercises/math/_debug/debugReorder3.d.ts.map +1 -0
- package/lib/exercises/math/_debug/debugReorder3.js +81 -0
- package/lib/exercises/math/_debug/index.d.ts +3 -1
- package/lib/exercises/math/_debug/index.d.ts.map +1 -1
- package/lib/exercises/math/_debug/index.js +3 -1
- package/lib/exercises/math/calcul/factorial/index.d.ts +2 -0
- package/lib/exercises/math/calcul/factorial/index.d.ts.map +1 -0
- package/lib/exercises/math/calcul/factorial/index.js +1 -0
- package/lib/exercises/math/calcul/factorial/simplifyQuotientOfFactorialToProduct.d.ts +8 -0
- package/lib/exercises/math/calcul/factorial/simplifyQuotientOfFactorialToProduct.d.ts.map +1 -0
- package/lib/exercises/math/calcul/factorial/simplifyQuotientOfFactorialToProduct.js +199 -0
- package/lib/exercises/math/calculLitteral/equation/exp/expOfTrinomEquals1Equation.d.ts.map +1 -1
- package/lib/exercises/math/calculLitteral/equation/exp/expOfTrinomEquals1Equation.js +3 -0
- package/lib/exercises/math/calculLitteral/inequations/firstDegreeInequationsType3.d.ts.map +1 -1
- package/lib/exercises/math/calculLitteral/inequations/firstDegreeInequationsType3.js +58 -30
- package/lib/exercises/math/combinatory/combination/index.d.ts +3 -0
- package/lib/exercises/math/combinatory/combination/index.d.ts.map +1 -0
- package/lib/exercises/math/combinatory/combination/index.js +2 -0
- package/lib/exercises/math/combinatory/combination/mentalCalculateCombination.d.ts +11 -0
- package/lib/exercises/math/combinatory/combination/mentalCalculateCombination.d.ts.map +1 -0
- package/lib/exercises/math/combinatory/combination/mentalCalculateCombination.js +225 -0
- package/lib/exercises/math/combinatory/combination/writeCombinationFormulaUsingFactorial.d.ts +13 -0
- package/lib/exercises/math/combinatory/combination/writeCombinationFormulaUsingFactorial.d.ts.map +1 -0
- package/lib/exercises/math/combinatory/combination/writeCombinationFormulaUsingFactorial.js +285 -0
- package/lib/exercises/math/complex/addComplex.d.ts.map +1 -1
- package/lib/exercises/math/complex/addComplex.js +53 -7
- package/lib/exercises/math/complex/conjugateComplex.d.ts.map +1 -1
- package/lib/exercises/math/complex/conjugateComplex.js +48 -7
- package/lib/exercises/math/complex/mutiplyComplex.d.ts.map +1 -1
- package/lib/exercises/math/complex/mutiplyComplex.js +51 -18
- package/lib/exercises/math/complex/reAndIm.d.ts.map +1 -1
- package/lib/exercises/math/complex/reAndIm.js +35 -4
- package/lib/exercises/math/dataRepresentations/scatterPlot/scatterPlotInterpreting.d.ts.map +1 -1
- package/lib/exercises/math/dataRepresentations/scatterPlot/scatterPlotInterpreting.js +1 -1
- package/lib/exercises/math/derivation/derivative/trigo/cosSecondDegreeDerivative.d.ts.map +1 -1
- package/lib/exercises/math/derivation/derivative/trigo/cosSecondDegreeDerivative.js +47 -3
- package/lib/exercises/math/derivation/derivative/trigo/productOfSinAXPlusBCosCXPlusDDerivative.d.ts +9 -0
- package/lib/exercises/math/derivation/derivative/trigo/productOfSinAXPlusBCosCXPlusDDerivative.d.ts.map +1 -0
- package/lib/exercises/math/derivation/derivative/trigo/productOfSinAXPlusBCosCXPlusDDerivative.js +209 -0
- package/lib/exercises/math/derivation/derivative/trigo/sinAndCosMixedWithSquareDerivative.d.ts +9 -0
- package/lib/exercises/math/derivation/derivative/trigo/sinAndCosMixedWithSquareDerivative.d.ts.map +1 -0
- package/lib/exercises/math/derivation/derivative/trigo/sinAndCosMixedWithSquareDerivative.js +359 -0
- package/lib/exercises/math/derivation/derivative/trigo/sinCosDerivativeRewriteUsingCos2PlusSin2Equals1.d.ts +11 -0
- package/lib/exercises/math/derivation/derivative/trigo/sinCosDerivativeRewriteUsingCos2PlusSin2Equals1.d.ts.map +1 -0
- package/lib/exercises/math/derivation/derivative/trigo/sinCosDerivativeRewriteUsingCos2PlusSin2Equals1.js +445 -0
- package/lib/exercises/math/functions/affines/affineVarTableOnBoundedInterval.d.ts.map +1 -1
- package/lib/exercises/math/functions/affines/affineVarTableOnBoundedInterval.js +2 -3
- package/lib/exercises/math/functions/exponential/sign/expFunctionBasicSign.d.ts.map +1 -1
- package/lib/exercises/math/functions/exponential/sign/expFunctionBasicSign.js +3 -0
- package/lib/exercises/math/functions/sign/affineProductSign.d.ts.map +1 -1
- package/lib/exercises/math/functions/sign/affineProductSign.js +0 -4
- package/lib/exercises/math/index.d.ts +1 -0
- package/lib/exercises/math/index.d.ts.map +1 -1
- package/lib/exercises/math/index.js +1 -1
- package/lib/exercises/math/limits/sequenceGeometricLimit.d.ts.map +1 -1
- package/lib/exercises/math/limits/sequenceGeometricLimit.js +9 -0
- package/lib/exercises/math/primitive/constantPrimitive.d.ts +8 -5
- package/lib/exercises/math/primitive/constantPrimitive.d.ts.map +1 -1
- package/lib/exercises/math/primitive/constantPrimitive.js +40 -21
- package/lib/exercises/math/probaStat/stats2var/averagePoint.d.ts.map +1 -1
- package/lib/exercises/math/probaStat/stats2var/averagePoint.js +34 -2
- package/lib/exercises/math/sequences/geometric/graph/geometricFindThresholdFromGraph.d.ts +15 -0
- package/lib/exercises/math/sequences/geometric/graph/geometricFindThresholdFromGraph.d.ts.map +1 -0
- package/lib/exercises/math/sequences/geometric/graph/geometricFindThresholdFromGraph.js +255 -0
- package/lib/exercises/math/sequences/geometric/graph/geometricFindThresholdUsingCalculator.d.ts +15 -0
- package/lib/exercises/math/sequences/geometric/graph/geometricFindThresholdUsingCalculator.d.ts.map +1 -0
- package/lib/exercises/math/sequences/geometric/graph/geometricFindThresholdUsingCalculator.js +242 -0
- package/lib/exercises/math/sequences/geometric/graph/geometricPlaceFirstPoints.js +4 -4
- package/lib/exercises/math/sequences/geometric/graph/geometricSignOfReasonFromGraph.d.ts +12 -0
- package/lib/exercises/math/sequences/geometric/graph/geometricSignOfReasonFromGraph.d.ts.map +1 -0
- package/lib/exercises/math/sequences/geometric/graph/geometricSignOfReasonFromGraph.js +161 -0
- package/lib/exercises/math/sets/cartesianProduct/findCardinalOfCartesianProductOfFiniteSets.d.ts +10 -0
- package/lib/exercises/math/sets/cartesianProduct/findCardinalOfCartesianProductOfFiniteSets.d.ts.map +1 -0
- package/lib/exercises/math/sets/cartesianProduct/findCardinalOfCartesianProductOfFiniteSets.js +224 -0
- package/lib/exercises/math/sets/cartesianProduct/findCardinalOfCartesianProductOfFiniteSetsFromSituation.d.ts +18 -0
- package/lib/exercises/math/sets/cartesianProduct/findCardinalOfCartesianProductOfFiniteSetsFromSituation.d.ts.map +1 -0
- package/lib/exercises/math/sets/cartesianProduct/findCardinalOfCartesianProductOfFiniteSetsFromSituation.js +198 -0
- package/lib/exercises/math/sets/cartesianProduct/findCardinalOfPowEK.d.ts +10 -0
- package/lib/exercises/math/sets/cartesianProduct/findCardinalOfPowEK.d.ts.map +1 -0
- package/lib/exercises/math/sets/cartesianProduct/findCardinalOfPowEK.js +231 -0
- package/lib/exercises/math/sets/cartesianProduct/findNumberOfPasswordsWithLettersAndNumbers.d.ts +19 -0
- package/lib/exercises/math/sets/cartesianProduct/findNumberOfPasswordsWithLettersAndNumbers.d.ts.map +1 -0
- package/lib/exercises/math/sets/cartesianProduct/findNumberOfPasswordsWithLettersAndNumbers.js +187 -0
- package/lib/exercises/math/sets/cartesianProduct/index.d.ts +7 -0
- package/lib/exercises/math/sets/cartesianProduct/index.d.ts.map +1 -0
- package/lib/exercises/math/sets/cartesianProduct/index.js +6 -0
- package/lib/exercises/math/sets/cartesianProduct/proposeElementInCartesianProductOfFiniteSets.d.ts +15 -0
- package/lib/exercises/math/sets/cartesianProduct/proposeElementInCartesianProductOfFiniteSets.d.ts.map +1 -0
- package/lib/exercises/math/sets/cartesianProduct/proposeElementInCartesianProductOfFiniteSets.js +291 -0
- package/lib/exercises/math/sets/cartesianProduct/proposeElementInPowEK.d.ts +15 -0
- package/lib/exercises/math/sets/cartesianProduct/proposeElementInPowEK.d.ts.map +1 -0
- package/lib/exercises/math/sets/cartesianProduct/proposeElementInPowEK.js +274 -0
- package/lib/exercises/math/sets/combinations/findNumberOfCombinationsFromSituation.d.ts +17 -0
- package/lib/exercises/math/sets/combinations/findNumberOfCombinationsFromSituation.d.ts.map +1 -0
- package/lib/exercises/math/sets/combinations/findNumberOfCombinationsFromSituation.js +228 -0
- package/lib/exercises/math/sets/combinations/findNumberOfProductsOfCombinationsFromSituation.d.ts +17 -0
- package/lib/exercises/math/sets/combinations/findNumberOfProductsOfCombinationsFromSituation.d.ts.map +1 -0
- package/lib/exercises/math/sets/combinations/findNumberOfProductsOfCombinationsFromSituation.js +388 -0
- package/lib/exercises/math/sets/combinations/index.d.ts +4 -0
- package/lib/exercises/math/sets/combinations/index.d.ts.map +1 -0
- package/lib/exercises/math/sets/combinations/index.js +3 -0
- package/lib/exercises/math/sets/combinations/proposeCombination.d.ts +15 -0
- package/lib/exercises/math/sets/combinations/proposeCombination.d.ts.map +1 -0
- package/lib/exercises/math/sets/combinations/proposeCombination.js +347 -0
- package/lib/exercises/math/sets/partialPermutations/findNumberOfPartialPermutationsFromSituation.d.ts +16 -0
- package/lib/exercises/math/sets/partialPermutations/findNumberOfPartialPermutationsFromSituation.d.ts.map +1 -0
- package/lib/exercises/math/sets/partialPermutations/findNumberOfPartialPermutationsFromSituation.js +186 -0
- package/lib/exercises/math/sets/partialPermutations/findNumberOfPermutationsFromSituation.d.ts +17 -0
- package/lib/exercises/math/sets/partialPermutations/findNumberOfPermutationsFromSituation.d.ts.map +1 -0
- package/lib/exercises/math/sets/partialPermutations/findNumberOfPermutationsFromSituation.js +232 -0
- package/lib/exercises/math/sets/partialPermutations/index.d.ts +4 -0
- package/lib/exercises/math/sets/partialPermutations/index.d.ts.map +1 -0
- package/lib/exercises/math/sets/partialPermutations/index.js +3 -0
- package/lib/exercises/math/sets/partialPermutations/proposePartialPermutation.d.ts +15 -0
- package/lib/exercises/math/sets/partialPermutations/proposePartialPermutation.d.ts.map +1 -0
- package/lib/exercises/math/sets/partialPermutations/proposePartialPermutation.js +343 -0
- package/lib/exercises/math/spaceGeometry/vectors/spaceVectorLinearCombinationCoords.d.ts.map +1 -1
- package/lib/exercises/math/trigonometry/functions/parityOfCosAXTimesSinBX.d.ts +8 -0
- package/lib/exercises/math/trigonometry/functions/parityOfCosAXTimesSinBX.d.ts.map +1 -0
- package/lib/exercises/math/trigonometry/functions/parityOfCosAXTimesSinBX.js +193 -0
- package/lib/index.d.ts +15 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/math/sets/setOperations.d.ts +9 -0
- package/lib/math/sets/setOperations.d.ts.map +1 -0
- package/lib/math/sets/setOperations.js +84 -0
- package/lib/math/sets/tuple.d.ts +12 -0
- package/lib/math/sets/tuple.d.ts.map +1 -0
- package/lib/math/sets/tuple.js +17 -0
- package/lib/server.js +28 -2
- package/lib/tests/pdfExo.test.js +2 -2
- package/lib/tests/pdfs/buildPDFForExercise.d.ts.map +1 -1
- package/lib/tests/pdfs/buildPDFForExercise.js +6 -0
- package/lib/tests/pdfs/quizPdfPreambule.d.ts.map +1 -1
- package/lib/tests/pdfs/quizPdfPreambule.js +1 -0
- package/lib/tests/pdfs/treeDiagramToLatex.d.ts +15 -0
- package/lib/tests/pdfs/treeDiagramToLatex.d.ts.map +1 -0
- package/lib/tests/pdfs/treeDiagramToLatex.js +49 -0
- package/lib/tests/questionTest.d.ts.map +1 -1
- package/lib/tests/questionTest.js +19 -0
- package/lib/tree/utilities/nodePrinter.d.ts +7 -0
- package/lib/tree/utilities/nodePrinter.d.ts.map +1 -0
- package/lib/tree/utilities/nodePrinter.js +36 -0
- package/package.json +1 -1
|
@@ -7,6 +7,9 @@ import { Affine } from "../../../../math/polynomials/affine.js";
|
|
|
7
7
|
import { randint } from "../../../../math/utils/random/randint.js";
|
|
8
8
|
import { InequationNode } from "../../../../tree/nodes/inequations/inequationNode.js";
|
|
9
9
|
import { InequationSolutionNode } from "../../../../tree/nodes/inequations/inequationSolutionNode.js";
|
|
10
|
+
import { add } from "../../../../tree/nodes/operators/addNode.js";
|
|
11
|
+
import { multiply } from "../../../../tree/nodes/operators/multiplyNode.js";
|
|
12
|
+
import { substract } from "../../../../tree/nodes/operators/substractNode.js";
|
|
10
13
|
import { inequationParser } from "../../../../tree/parsers/inequationParser.js";
|
|
11
14
|
import { intervalParser } from "../../../../tree/parsers/intervalParser.js";
|
|
12
15
|
import { coinFlip } from "../../../../utils/alea/coinFlip.js";
|
|
@@ -41,37 +44,59 @@ const getAnswerNode = (identifiers, opts) => {
|
|
|
41
44
|
const getAnswer = (identifiers, opts) => {
|
|
42
45
|
return getAnswerNode(identifiers, opts).toTex();
|
|
43
46
|
};
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
47
|
+
const getHint = () => {
|
|
48
|
+
return `Commence par regrouper les termes en $x$ d'un même côté de l'inéquation. Puis isole $x$ en effectuant les bonnes opérations.
|
|
49
|
+
|
|
50
|
+
Attention, lorsqu'on divise ou multiplie les deux membres d'une inéquation par un nombre négatif, l'inéquation change de sens. `;
|
|
51
|
+
};
|
|
52
|
+
const getCorrection = (identifiers, opts) => {
|
|
53
|
+
const { a, b, c, d, ineqType } = identifiers;
|
|
54
|
+
const affine1 = new Affine(a, b);
|
|
55
|
+
const affine2 = new Affine(c, d);
|
|
56
|
+
const isInterval = opts?.inequationSolutionFormat === "Intervalle (S = [a;b])";
|
|
57
|
+
return `On doit résoudre l'inéquation :
|
|
58
|
+
|
|
59
|
+
$$
|
|
60
|
+
${affine1.toTex()} ${ineqType} ${affine2.toTex()}
|
|
61
|
+
$$
|
|
62
|
+
|
|
63
|
+
On ${c < 0 ? "ajoute" : "enlève"} $${multiply(Math.abs(c), "x").toTex()}$ des deux côtés :
|
|
64
|
+
|
|
65
|
+
$$
|
|
66
|
+
${add(multiply(substract(a, c).simplify(), "x"), b).toTex()} ${ineqType} ${d.frenchify()}
|
|
67
|
+
$$
|
|
68
|
+
|
|
69
|
+
On ${b < 0 ? "ajoute" : "enlève"} $${Math.abs(b).frenchify()}$ des deux côtés :
|
|
70
|
+
|
|
71
|
+
$$
|
|
72
|
+
${multiply(substract(a, c).simplify(), "x").toTex()} ${ineqType} ${substract(d, b)
|
|
73
|
+
.simplify()
|
|
74
|
+
.toTex()}
|
|
75
|
+
$$
|
|
76
|
+
|
|
77
|
+
On divise ensuite par $${substract(a, c)
|
|
78
|
+
.simplify()
|
|
79
|
+
.toTex()}$. Puisque $${substract(a, c).simplify().toTex()}$ est ${a > c ? "positif" : "négatif"}, l'inéquation ${a > c ? "ne change pas" : "change"} de sens :
|
|
80
|
+
|
|
81
|
+
$$
|
|
82
|
+
${getAnswer(identifiers, {
|
|
83
|
+
inequationSolutionFormat: "Inégalité (x>a)",
|
|
84
|
+
})}
|
|
85
|
+
$$
|
|
86
|
+
|
|
87
|
+
${isInterval
|
|
88
|
+
? `On traduit cette inégalité par un intervalle :
|
|
89
|
+
|
|
90
|
+
$$
|
|
91
|
+
${getAnswer(identifiers, opts)}
|
|
92
|
+
$$`
|
|
93
|
+
: ""}
|
|
94
|
+
`;
|
|
95
|
+
};
|
|
72
96
|
const getFirstDegreeInequationsQuestion = (opts) => {
|
|
73
|
-
|
|
74
|
-
const
|
|
97
|
+
// ax+b < cx+d
|
|
98
|
+
const affine1 = new Affine(randint(-10, 10, [0, 1]), randint(-10, 10, [0]));
|
|
99
|
+
const affine2 = new Affine(randint(-10, 10, [0, affine1.a, 1, affine1.a - 1]), randint(-10, 10, [0]));
|
|
75
100
|
const coeff = affine1.a - affine2.a;
|
|
76
101
|
const ineqType = InequationSymbolConstructor.random();
|
|
77
102
|
const identifiers = {
|
|
@@ -91,6 +116,8 @@ const getQuestionFromIdentifiers = (identifiers, opts) => {
|
|
|
91
116
|
keys: getKeys(identifiers, opts),
|
|
92
117
|
answerFormat: "tex",
|
|
93
118
|
identifiers,
|
|
119
|
+
hint: getHint(identifiers, opts),
|
|
120
|
+
correction: getCorrection(identifiers, opts),
|
|
94
121
|
};
|
|
95
122
|
return question;
|
|
96
123
|
};
|
|
@@ -157,6 +184,7 @@ export const firstDegreeInequationsType3 = {
|
|
|
157
184
|
subject: "Mathématiques",
|
|
158
185
|
options,
|
|
159
186
|
getQuestionFromIdentifiers,
|
|
187
|
+
hasHintAndCorrection: true,
|
|
160
188
|
};
|
|
161
189
|
// export const reuseFirstDegreeInequationsType3 = {
|
|
162
190
|
// getAnswerNode,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/combinatory/combination/index.ts"],"names":[],"mappings":"AAAA,cAAc,4CAA4C,CAAC;AAC3D,cAAc,iCAAiC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Exercise } from "../../../../exercises/exercise.js";
|
|
2
|
+
type Identifiers = {
|
|
3
|
+
total: number;
|
|
4
|
+
picked: number;
|
|
5
|
+
};
|
|
6
|
+
type Options = {
|
|
7
|
+
statementFormulaType: string;
|
|
8
|
+
};
|
|
9
|
+
export declare const mentalCalculateCombination: Exercise<Identifiers, Options>;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=mentalCalculateCombination.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mentalCalculateCombination.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/combinatory/combination/mentalCalculateCombination.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAmBT,MAAM,6BAA6B,CAAC;AAarC,KAAK,WAAW,GAAG;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AA8OF,KAAK,OAAO,GAAG;IACb,oBAAoB,EAAE,MAAM,CAAC;CAC9B,CAAC;AAgBF,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,WAAW,EAAE,OAAO,CAkBrE,CAAC"}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { GeneratorOptionTarget, GeneratorOptionType, addValidProp, propWhile, shuffleProps, tryToAddWrongProp, } from "../../../../exercises/exercise.js";
|
|
2
|
+
import { numberVEA } from "../../../../exercises/vea/numberVEA.js";
|
|
3
|
+
import { randint } from "../../../../math/utils/random/randint.js";
|
|
4
|
+
import { facto } from "../../../../tree/nodes/functions/factorialNode.js";
|
|
5
|
+
import { binom } from "../../../../tree/nodes/operators/binomialCoefficientNode.js";
|
|
6
|
+
import { frac } from "../../../../tree/nodes/operators/fractionNode.js";
|
|
7
|
+
import { multiply } from "../../../../tree/nodes/operators/multiplyNode.js";
|
|
8
|
+
import { substract } from "../../../../tree/nodes/operators/substractNode.js";
|
|
9
|
+
import { coinFlip } from "../../../../utils/alea/coinFlip.js";
|
|
10
|
+
import { handleVEAError } from "../../../../utils/errors/handleVEAError.js";
|
|
11
|
+
import { alignTex } from "../../../../utils/latex/alignTex.js";
|
|
12
|
+
const getInstruction = (identifiers, optsIn) => {
|
|
13
|
+
const opts = optsIn ?? optsDefault;
|
|
14
|
+
const { statementFormulaType } = opts;
|
|
15
|
+
const { total, picked } = identifiers;
|
|
16
|
+
const texFormula = (() => {
|
|
17
|
+
switch (statementFormulaType) {
|
|
18
|
+
case "$\\binom{n}{k}$":
|
|
19
|
+
return binom(total, picked).toTex();
|
|
20
|
+
case "$\\frac{n!}{k!(n-k)!}$":
|
|
21
|
+
return binom(total, picked).toFormulaWithFactoFractionNode().toTex();
|
|
22
|
+
default:
|
|
23
|
+
throw new Error("Unsupported statementFormulaType:" + statementFormulaType);
|
|
24
|
+
}
|
|
25
|
+
})();
|
|
26
|
+
return `Sans calculatrice, et en utilisant des simplifications, calculer :
|
|
27
|
+
|
|
28
|
+
$$
|
|
29
|
+
${texFormula}
|
|
30
|
+
$$`;
|
|
31
|
+
};
|
|
32
|
+
const getAnswerStuff = (identifiers) => {
|
|
33
|
+
const { total, picked } = identifiers;
|
|
34
|
+
const nodeBinom = binom(total, picked);
|
|
35
|
+
const nodeFormulaRaw = nodeBinom.toFormulaWithFactoFractionNode();
|
|
36
|
+
const nodeAnswer = nodeBinom.toFormulaWithoutFacto();
|
|
37
|
+
return { nodeBinom, nodeFormulaRaw, nodeAnswer };
|
|
38
|
+
};
|
|
39
|
+
const getAnswer = (identifiers) => {
|
|
40
|
+
return getAnswerStuff(identifiers)
|
|
41
|
+
.nodeAnswer.simplify({
|
|
42
|
+
towardsDistribute: true,
|
|
43
|
+
})
|
|
44
|
+
.toTex();
|
|
45
|
+
};
|
|
46
|
+
const getHint = (identifiers) => {
|
|
47
|
+
const { total, picked } = identifiers;
|
|
48
|
+
const { nodeBinom, nodeFormulaRaw } = getAnswerStuff(identifiers);
|
|
49
|
+
return `Voici la formule pour $${picked}$ parmi $${total}$:
|
|
50
|
+
|
|
51
|
+
$$
|
|
52
|
+
${nodeBinom.toTex()} = ${nodeFormulaRaw.toTex()}
|
|
53
|
+
$$
|
|
54
|
+
|
|
55
|
+
Voici les produits qui correspondent à chaque factorielle :
|
|
56
|
+
|
|
57
|
+
${alignTex([facto(total), facto(picked), facto(total - picked)].flatMap((nodeFacto) => {
|
|
58
|
+
const texExpanded = nodeFacto
|
|
59
|
+
.toMultiplyNode()
|
|
60
|
+
.toTex({ forceNoSimplification: true, forceTimesSign: true });
|
|
61
|
+
const arrTexFactor = texExpanded.split("\\times");
|
|
62
|
+
const arrArrTexFactor = arrTexFactor.reduce((acc, texFactor, i, arr) => {
|
|
63
|
+
acc.running.push(texFactor);
|
|
64
|
+
if (acc.running.length >= 4 || i === arr.length - 1) {
|
|
65
|
+
acc.chunks.push(acc.running);
|
|
66
|
+
acc.running = [];
|
|
67
|
+
}
|
|
68
|
+
return acc;
|
|
69
|
+
}, {
|
|
70
|
+
chunks: [],
|
|
71
|
+
running: [],
|
|
72
|
+
}).chunks;
|
|
73
|
+
return arrArrTexFactor.map((arrTexFactor, i) => {
|
|
74
|
+
const texChunk = arrTexFactor.join(" \\times ");
|
|
75
|
+
if (i === 0) {
|
|
76
|
+
return [nodeFacto.toTex(), "= \\ \\ \\ ", texChunk];
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
return [" ", "\\ \\ \\ \\times", texChunk];
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}))}
|
|
83
|
+
|
|
84
|
+
Remplace chaque factorielle par le produit qui lui correspond puis simplifie quand le même terme apparaît au numérateur et au dénominateur.
|
|
85
|
+
`;
|
|
86
|
+
};
|
|
87
|
+
const getCorrection = (identifiers) => {
|
|
88
|
+
const { total, picked } = identifiers;
|
|
89
|
+
const { nodeBinom, nodeFormulaRaw, nodeAnswer } = getAnswerStuff(identifiers);
|
|
90
|
+
const nodeFracFacto = frac(facto(total), facto(picked));
|
|
91
|
+
const nodeNum = nodeAnswer.leftChild;
|
|
92
|
+
return `Voici la formule pour $${picked}$ parmi $${total}$:
|
|
93
|
+
|
|
94
|
+
$$
|
|
95
|
+
${nodeBinom.toTex()} = ${nodeFormulaRaw.toTex()}
|
|
96
|
+
$$
|
|
97
|
+
|
|
98
|
+
Or :
|
|
99
|
+
|
|
100
|
+
$$
|
|
101
|
+
${nodeFracFacto.toTex()} = ${nodeNum.toTex()}
|
|
102
|
+
$$
|
|
103
|
+
|
|
104
|
+
Donc:
|
|
105
|
+
|
|
106
|
+
${alignTex([
|
|
107
|
+
[
|
|
108
|
+
nodeFormulaRaw.toTex(),
|
|
109
|
+
"=",
|
|
110
|
+
nodeAnswer.toTex({ forceTimesSign: true, forceNoSimplification: true }),
|
|
111
|
+
],
|
|
112
|
+
["", "=", nodeAnswer.simplify({ towardsDistribute: true }).toTex()],
|
|
113
|
+
])}
|
|
114
|
+
|
|
115
|
+
`;
|
|
116
|
+
};
|
|
117
|
+
const getPropositions = (n, { answer, ...identifiers }) => {
|
|
118
|
+
const { total, picked } = identifiers;
|
|
119
|
+
const propositions = [];
|
|
120
|
+
addValidProp(propositions, answer);
|
|
121
|
+
function checkAndTryToAddNode(node) {
|
|
122
|
+
const value = node.evaluate();
|
|
123
|
+
if (0.01 <= value && value <= 220) {
|
|
124
|
+
tryToAddWrongProp(propositions, node.simplify({ towardsDistribute: true }).toTex());
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
//student: total!/(total-picked)!
|
|
128
|
+
{
|
|
129
|
+
const node = frac(facto(total), facto(substract(total, picked)));
|
|
130
|
+
checkAndTryToAddNode(node);
|
|
131
|
+
}
|
|
132
|
+
//student: total!/picked!
|
|
133
|
+
{
|
|
134
|
+
const node = frac(facto(total), facto(picked));
|
|
135
|
+
checkAndTryToAddNode(node);
|
|
136
|
+
}
|
|
137
|
+
//student: picked!/total!
|
|
138
|
+
{
|
|
139
|
+
const node = frac(facto(total), facto(picked));
|
|
140
|
+
checkAndTryToAddNode(node);
|
|
141
|
+
}
|
|
142
|
+
//student: forgets factorial somewhere
|
|
143
|
+
{
|
|
144
|
+
{
|
|
145
|
+
const node = frac(facto(total), multiply(picked, facto(substract(total, picked))));
|
|
146
|
+
checkAndTryToAddNode(node);
|
|
147
|
+
}
|
|
148
|
+
{
|
|
149
|
+
const node = frac(facto(picked), multiply(total, facto(substract(total, picked))));
|
|
150
|
+
checkAndTryToAddNode(node);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
propWhile(propositions, n, () => {
|
|
154
|
+
const identifiersWrong = createRandomIdentifiers();
|
|
155
|
+
tryToAddWrongProp(propositions, getAnswer(identifiersWrong));
|
|
156
|
+
});
|
|
157
|
+
return shuffleProps(propositions, n);
|
|
158
|
+
};
|
|
159
|
+
const getKeys = () => {
|
|
160
|
+
return [];
|
|
161
|
+
};
|
|
162
|
+
const isAnswerValid = (ans, { answer }) => {
|
|
163
|
+
try {
|
|
164
|
+
return numberVEA(ans, answer);
|
|
165
|
+
}
|
|
166
|
+
catch (err) {
|
|
167
|
+
return handleVEAError(err);
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
const createRandomIdentifiers = () => {
|
|
171
|
+
const total = randint(5, 13);
|
|
172
|
+
const nbFactors = randint(2, 4);
|
|
173
|
+
const picked = coinFlip() ? nbFactors : total - nbFactors;
|
|
174
|
+
return {
|
|
175
|
+
total,
|
|
176
|
+
picked,
|
|
177
|
+
};
|
|
178
|
+
};
|
|
179
|
+
const getMentalCalculateCombinationQuestion = (optsIn) => {
|
|
180
|
+
const opts = optsIn ?? optsDefault;
|
|
181
|
+
const identifiers = createRandomIdentifiers();
|
|
182
|
+
return getQuestionFromIdentifiers(identifiers, opts);
|
|
183
|
+
};
|
|
184
|
+
const getQuestionFromIdentifiers = (identifiers, opts) => {
|
|
185
|
+
const question = {
|
|
186
|
+
instruction: getInstruction(identifiers, opts),
|
|
187
|
+
answer: getAnswer(identifiers),
|
|
188
|
+
keys: getKeys(identifiers),
|
|
189
|
+
answerFormat: "tex",
|
|
190
|
+
identifiers,
|
|
191
|
+
hint: getHint(identifiers),
|
|
192
|
+
correction: getCorrection(identifiers),
|
|
193
|
+
options: opts,
|
|
194
|
+
};
|
|
195
|
+
return question;
|
|
196
|
+
};
|
|
197
|
+
const optsDefault = {
|
|
198
|
+
statementFormulaType: "$\\binom{n}{k}$",
|
|
199
|
+
};
|
|
200
|
+
const options = [
|
|
201
|
+
{
|
|
202
|
+
id: "statementFormulaType",
|
|
203
|
+
label: "Type de formule dans l'énoncé",
|
|
204
|
+
target: GeneratorOptionTarget.generation,
|
|
205
|
+
type: GeneratorOptionType.select,
|
|
206
|
+
values: ["$\\binom{n}{k}$", "$\\frac{n!}{k!(n-k)!}$"],
|
|
207
|
+
defaultValue: optsDefault.statementFormulaType,
|
|
208
|
+
},
|
|
209
|
+
];
|
|
210
|
+
export const mentalCalculateCombination = {
|
|
211
|
+
id: "mentalCalculateCombination",
|
|
212
|
+
connector: "=",
|
|
213
|
+
label: "Calculer une combinaison sans calculatrice",
|
|
214
|
+
isSingleStep: true,
|
|
215
|
+
generator: (nb, opts) => [...Array(nb).keys()].map(() => getMentalCalculateCombinationQuestion(opts)),
|
|
216
|
+
options,
|
|
217
|
+
qcmTimer: 60,
|
|
218
|
+
freeTimer: 60,
|
|
219
|
+
getPropositions,
|
|
220
|
+
isAnswerValid,
|
|
221
|
+
subject: "Mathématiques",
|
|
222
|
+
getQuestionFromIdentifiers,
|
|
223
|
+
hasHintAndCorrection: true,
|
|
224
|
+
shouldHaveCalculator: false,
|
|
225
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Exercise } from "../../../../exercises/exercise.js";
|
|
2
|
+
import { NodeIdentifiers } from "../../../../tree/nodes/nodeConstructor.js";
|
|
3
|
+
type Identifiers = {
|
|
4
|
+
nodeIdsTotal: NodeIdentifiers;
|
|
5
|
+
nodeIdsPicked: NodeIdentifiers;
|
|
6
|
+
operandType: string;
|
|
7
|
+
};
|
|
8
|
+
type Options = {
|
|
9
|
+
operandType: string;
|
|
10
|
+
};
|
|
11
|
+
export declare const writeCombinationFormulaUsingFactorial: Exercise<Identifiers, Options>;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=writeCombinationFormulaUsingFactorial.d.ts.map
|
package/lib/exercises/math/combinatory/combination/writeCombinationFormulaUsingFactorial.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writeCombinationFormulaUsingFactorial.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/combinatory/combination/writeCombinationFormulaUsingFactorial.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAkBT,MAAM,6BAA6B,CAAC;AAMrC,OAAO,EAEL,eAAe,EAChB,MAAM,qCAAqC,CAAC;AAiB7C,KAAK,WAAW,GAAG;IACjB,YAAY,EAAE,eAAe,CAAC;IAC9B,aAAa,EAAE,eAAe,CAAC;IAC/B,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AA2UF,KAAK,OAAO,GAAG;IACb,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAsBF,eAAO,MAAM,qCAAqC,EAAE,QAAQ,CAC1D,WAAW,EACX,OAAO,CAoBR,CAAC"}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { GeneratorOptionTarget, GeneratorOptionType, addValidProp, shuffleProps, tryToAddWrongProp, } from "../../../../exercises/exercise.js";
|
|
2
|
+
import { getDistinctQuestions } from "../../../../exercises/utils/getDistinctQuestions.js";
|
|
3
|
+
import { defaultArrayedOptsWhereNeeded } from "../../../../exercises/utils/options/arrayedOptions.js";
|
|
4
|
+
import { randint } from "../../../../math/utils/random/randint.js";
|
|
5
|
+
import { facto } from "../../../../tree/nodes/functions/factorialNode.js";
|
|
6
|
+
import { NodeConstructor, } from "../../../../tree/nodes/nodeConstructor.js";
|
|
7
|
+
import { binom } from "../../../../tree/nodes/operators/binomialCoefficientNode.js";
|
|
8
|
+
import { frac } from "../../../../tree/nodes/operators/fractionNode.js";
|
|
9
|
+
import { multiply, } from "../../../../tree/nodes/operators/multiplyNode.js";
|
|
10
|
+
import { substract } from "../../../../tree/nodes/operators/substractNode.js";
|
|
11
|
+
import { VariableNode } from "../../../../tree/nodes/variables/variableNode.js";
|
|
12
|
+
import { parseAlgebraic } from "../../../../tree/parsers/latexParser.js";
|
|
13
|
+
import { NodeComparator } from "../../../../tree/utilities/nodeComparator.js";
|
|
14
|
+
import { random, randomMany } from "../../../../utils/alea/random.js";
|
|
15
|
+
import { handleVEAError } from "../../../../utils/errors/handleVEAError.js";
|
|
16
|
+
import { alignTex } from "../../../../utils/latex/alignTex.js";
|
|
17
|
+
const getInstruction = (identifiers) => {
|
|
18
|
+
const { nodeIdsTotal, nodeIdsPicked } = identifiers;
|
|
19
|
+
const [nodeTotal, nodePicked] = [nodeIdsTotal, nodeIdsPicked].map((nodeIds) => NodeConstructor.fromIdentifiers(nodeIds));
|
|
20
|
+
return `Ecrire à l'aide de la factorielle la formule permettant de calculer :
|
|
21
|
+
|
|
22
|
+
$$
|
|
23
|
+
${binom(nodeTotal, nodePicked).toTex()}
|
|
24
|
+
$$`;
|
|
25
|
+
};
|
|
26
|
+
const getAnswerStuff = (identifiers) => {
|
|
27
|
+
const { nodeIdsTotal, nodeIdsPicked } = identifiers;
|
|
28
|
+
const [nodeTotal, nodePicked] = [nodeIdsTotal, nodeIdsPicked].map((nodeIds) => NodeConstructor.fromIdentifiers(nodeIds));
|
|
29
|
+
const nodeBinom = binom(nodeTotal, nodePicked);
|
|
30
|
+
const nodeAnswer = nodeBinom.toFormulaWithFactoFractionNode();
|
|
31
|
+
return { nodeBinom, nodeAnswer };
|
|
32
|
+
};
|
|
33
|
+
const getAnswer = (identifiers) => {
|
|
34
|
+
return getAnswerStuff(identifiers).nodeAnswer.toTex({
|
|
35
|
+
forceParenthesis: true,
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
const getHint = () => {
|
|
39
|
+
return `Le nombre de combinaisons de $k$ élements parmi $n$ (noté $${binom(new VariableNode("n"), new VariableNode("k")).toTex()}$)
|
|
40
|
+
est égal au nombre de façon de prendre $k$ éléments parmi $n$ sans tenir compte de l'ordre.
|
|
41
|
+
|
|
42
|
+
Exemple:
|
|
43
|
+
`;
|
|
44
|
+
};
|
|
45
|
+
const getCorrection = (identifiers) => {
|
|
46
|
+
const { nodeIdsTotal, nodeIdsPicked, operandType } = identifiers;
|
|
47
|
+
const [nodeTotal, nodePicked] = [nodeIdsTotal, nodeIdsPicked].map((nodeIds) => NodeConstructor.fromIdentifiers(nodeIds));
|
|
48
|
+
const nodeBinom = binom(nodeTotal, nodePicked);
|
|
49
|
+
const nodeAnswerRaw = nodeBinom.toFormulaWithFactoFractionNode(false);
|
|
50
|
+
const nodeAnswerPretty = nodeBinom.toFormulaWithFactoFractionNode(true);
|
|
51
|
+
switch (operandType) {
|
|
52
|
+
case "lettres":
|
|
53
|
+
return `
|
|
54
|
+
|
|
55
|
+
$$
|
|
56
|
+
${nodeBinom.toTex()} = ${nodeBinom.toTex()}
|
|
57
|
+
$$
|
|
58
|
+
|
|
59
|
+
`;
|
|
60
|
+
case "entiers":
|
|
61
|
+
return `
|
|
62
|
+
|
|
63
|
+
${alignTex([
|
|
64
|
+
[nodeBinom.toTex(), "=", nodeAnswerRaw.toTex()],
|
|
65
|
+
["", "=", nodeAnswerPretty.toTex()],
|
|
66
|
+
])}
|
|
67
|
+
|
|
68
|
+
`;
|
|
69
|
+
default:
|
|
70
|
+
throw new Error("Unsupported operandType: " + operandType);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
const getPropositions = (n, { answer, ...identifiers }) => {
|
|
74
|
+
const { nodeIdsTotal, nodeIdsPicked, operandType } = identifiers;
|
|
75
|
+
const [nodeTotal, nodePicked] = [nodeIdsTotal, nodeIdsPicked].map((nodeIds) => NodeConstructor.fromIdentifiers(nodeIds));
|
|
76
|
+
const propositions = [];
|
|
77
|
+
addValidProp(propositions, answer);
|
|
78
|
+
//student: total<->picked
|
|
79
|
+
{
|
|
80
|
+
switch (operandType) {
|
|
81
|
+
case "lettres":
|
|
82
|
+
{
|
|
83
|
+
const node = frac(facto(nodePicked), multiply(facto(nodeTotal), facto(substract(nodePicked, nodeTotal))));
|
|
84
|
+
tryToAddWrongProp(propositions, node.toTex());
|
|
85
|
+
}
|
|
86
|
+
break;
|
|
87
|
+
case "entiers":
|
|
88
|
+
{
|
|
89
|
+
const node = frac(facto(nodePicked), multiply(facto(nodeTotal), facto(substract(nodeTotal, nodePicked).simplify({
|
|
90
|
+
towardsDistribute: true,
|
|
91
|
+
}))));
|
|
92
|
+
tryToAddWrongProp(propositions, node.toTex());
|
|
93
|
+
}
|
|
94
|
+
break;
|
|
95
|
+
default:
|
|
96
|
+
throw new Error("Unsupported operandType: " + operandType);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//student: total!/(total-picked)!
|
|
100
|
+
{
|
|
101
|
+
const node = frac(facto(nodeTotal), facto(substract(nodeTotal, nodePicked).simplify({ towardsDistribute: true })));
|
|
102
|
+
tryToAddWrongProp(propositions, node.toTex());
|
|
103
|
+
}
|
|
104
|
+
//student: total!/picked!
|
|
105
|
+
{
|
|
106
|
+
const node = frac(facto(nodeTotal), facto(nodePicked));
|
|
107
|
+
tryToAddWrongProp(propositions, node.toTex());
|
|
108
|
+
}
|
|
109
|
+
//student: picked!/total!
|
|
110
|
+
{
|
|
111
|
+
const node = frac(facto(nodePicked), facto(nodeTotal));
|
|
112
|
+
tryToAddWrongProp(propositions, node.toTex());
|
|
113
|
+
}
|
|
114
|
+
//student: forgets factorial somewhere
|
|
115
|
+
{
|
|
116
|
+
{
|
|
117
|
+
const node = frac(facto(nodeTotal), multiply(nodePicked, facto(substract(nodeTotal, nodePicked).simplify({
|
|
118
|
+
towardsDistribute: true,
|
|
119
|
+
}))));
|
|
120
|
+
tryToAddWrongProp(propositions, node.toTex());
|
|
121
|
+
}
|
|
122
|
+
switch (operandType) {
|
|
123
|
+
case "lettres":
|
|
124
|
+
{
|
|
125
|
+
{
|
|
126
|
+
const node = frac(facto(nodePicked), multiply(nodeTotal, facto(substract(nodePicked, nodeTotal))));
|
|
127
|
+
tryToAddWrongProp(propositions, node.toTex());
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
break;
|
|
131
|
+
case "entiers":
|
|
132
|
+
{
|
|
133
|
+
const node = frac(facto(nodePicked), multiply(nodeTotal, facto(substract(nodeTotal, nodePicked).simplify({
|
|
134
|
+
towardsDistribute: true,
|
|
135
|
+
}))));
|
|
136
|
+
tryToAddWrongProp(propositions, node.toTex());
|
|
137
|
+
}
|
|
138
|
+
break;
|
|
139
|
+
default:
|
|
140
|
+
throw new Error("Unsupported operandType: " + operandType);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return shuffleProps(propositions, n);
|
|
144
|
+
};
|
|
145
|
+
const getKeys = (identifiers) => {
|
|
146
|
+
const { operandType } = identifiers;
|
|
147
|
+
const keyFacto = {
|
|
148
|
+
id: "custom",
|
|
149
|
+
label: "!",
|
|
150
|
+
labelType: "tex",
|
|
151
|
+
mathfieldInstructions: {
|
|
152
|
+
method: "write",
|
|
153
|
+
content: "!",
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
switch (operandType) {
|
|
157
|
+
case "lettres": {
|
|
158
|
+
const { nodeIdsTotal, nodeIdsPicked } = identifiers;
|
|
159
|
+
const [nodeTotal, nodePicked] = [nodeIdsTotal, nodeIdsPicked].map((nodeIds) => NodeConstructor.fromIdentifiers(nodeIds));
|
|
160
|
+
return [
|
|
161
|
+
// "facto",
|
|
162
|
+
keyFacto,
|
|
163
|
+
...[nodeTotal, nodePicked].map((node) => node.name),
|
|
164
|
+
];
|
|
165
|
+
}
|
|
166
|
+
case "entiers":
|
|
167
|
+
// return ["facto"];
|
|
168
|
+
return [keyFacto];
|
|
169
|
+
default:
|
|
170
|
+
throw new Error("Unsupported operandType: " + operandType);
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
const isAnswerValid = (ans, { answer, ...identifiers }) => {
|
|
174
|
+
const { operandType } = identifiers;
|
|
175
|
+
switch (operandType) {
|
|
176
|
+
case "lettres": {
|
|
177
|
+
try {
|
|
178
|
+
//TODO: parse factorial
|
|
179
|
+
const nodeAnswer = getAnswerStuff(identifiers).nodeAnswer;
|
|
180
|
+
const isFormat1 = (str) => str === nodeAnswer.toTex();
|
|
181
|
+
const isFormat2 = (str) => str ===
|
|
182
|
+
(() => {
|
|
183
|
+
const nodeDenum = nodeAnswer.rightChild;
|
|
184
|
+
const nodeAnswer2 = frac(nodeAnswer.leftChild, multiply(nodeDenum.rightChild, nodeDenum.leftChild));
|
|
185
|
+
return nodeAnswer2;
|
|
186
|
+
})().toTex();
|
|
187
|
+
return isFormat1(ans) || isFormat2(ans);
|
|
188
|
+
}
|
|
189
|
+
catch (err) {
|
|
190
|
+
return handleVEAError(err);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
case "entiers": {
|
|
194
|
+
try {
|
|
195
|
+
//TODO: parse factorial
|
|
196
|
+
function countFactorialSymbols(str) {
|
|
197
|
+
return str.split("").filter((str) => str === "!").length;
|
|
198
|
+
}
|
|
199
|
+
if (countFactorialSymbols(ans) !== countFactorialSymbols(answer)) {
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
const nodeAns = parseAlgebraic(ans);
|
|
203
|
+
const nodeAnswer = parseAlgebraic(answer);
|
|
204
|
+
return NodeComparator.isEqualViaFrac(nodeAns, nodeAnswer);
|
|
205
|
+
}
|
|
206
|
+
catch (err) {
|
|
207
|
+
return handleVEAError(err);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
default:
|
|
211
|
+
throw new Error("Unsupported operandType: " + operandType);
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
const createRandomIdentifiers = (operandType) => {
|
|
215
|
+
switch (operandType) {
|
|
216
|
+
case "lettres": {
|
|
217
|
+
const poolLetters = "abcdklmnpqrst".split("");
|
|
218
|
+
const [nodeTotal, nodePicked] = randomMany(poolLetters, 2).map((letter) => new VariableNode(letter));
|
|
219
|
+
return {
|
|
220
|
+
nodeIdsTotal: nodeTotal.toIdentifiers(),
|
|
221
|
+
nodeIdsPicked: nodePicked.toIdentifiers(),
|
|
222
|
+
operandType,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
case "entiers": {
|
|
226
|
+
const total = randint(30, 61);
|
|
227
|
+
const picked = randint(5, 21);
|
|
228
|
+
const [nodeTotal, nodePicked] = [total, picked].map((v) => v.toTree());
|
|
229
|
+
return {
|
|
230
|
+
nodeIdsTotal: nodeTotal.toIdentifiers(),
|
|
231
|
+
nodeIdsPicked: nodePicked.toIdentifiers(),
|
|
232
|
+
operandType,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
default:
|
|
236
|
+
throw new Error("Unsupported operandType: " + operandType);
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
const getWriteCombinationFormulaUsingFactorialQuestion = (optsIn) => {
|
|
240
|
+
const arrayedOpts = defaultArrayedOptsWhereNeeded(optsIn, arrayedOptsDefault);
|
|
241
|
+
const operandType = random(arrayedOpts.operandType);
|
|
242
|
+
const identifiers = createRandomIdentifiers(operandType);
|
|
243
|
+
return getQuestionFromIdentifiers(identifiers);
|
|
244
|
+
};
|
|
245
|
+
const getQuestionFromIdentifiers = (identifiers) => {
|
|
246
|
+
const question = {
|
|
247
|
+
instruction: getInstruction(identifiers),
|
|
248
|
+
answer: getAnswer(identifiers),
|
|
249
|
+
keys: getKeys(identifiers),
|
|
250
|
+
answerFormat: "tex",
|
|
251
|
+
identifiers,
|
|
252
|
+
hint: getHint(identifiers),
|
|
253
|
+
correction: getCorrection(identifiers),
|
|
254
|
+
};
|
|
255
|
+
return question;
|
|
256
|
+
};
|
|
257
|
+
const arrayedOptsDefault = {
|
|
258
|
+
operandType: ["entiers"],
|
|
259
|
+
};
|
|
260
|
+
const options = [
|
|
261
|
+
{
|
|
262
|
+
id: "operandType",
|
|
263
|
+
label: "Type d'opérandes",
|
|
264
|
+
target: GeneratorOptionTarget.generation,
|
|
265
|
+
type: GeneratorOptionType.multiselect,
|
|
266
|
+
values: ["lettres", "entiers"],
|
|
267
|
+
defaultValue: arrayedOptsDefault.operandType,
|
|
268
|
+
},
|
|
269
|
+
];
|
|
270
|
+
export const writeCombinationFormulaUsingFactorial = {
|
|
271
|
+
id: "writeCombinationFormulaUsingFactorial",
|
|
272
|
+
connector: "=",
|
|
273
|
+
label: "Écrire à l'aide de factorielles la formule pour $\\binom{n}{k}$",
|
|
274
|
+
isSingleStep: true,
|
|
275
|
+
generator: (nb, opts) => getDistinctQuestions(() => getWriteCombinationFormulaUsingFactorialQuestion(opts), nb),
|
|
276
|
+
options,
|
|
277
|
+
qcmTimer: 60,
|
|
278
|
+
freeTimer: 60,
|
|
279
|
+
getPropositions,
|
|
280
|
+
isAnswerValid,
|
|
281
|
+
subject: "Mathématiques",
|
|
282
|
+
getQuestionFromIdentifiers,
|
|
283
|
+
hasHintAndCorrection: true,
|
|
284
|
+
shouldHaveCalculator: false,
|
|
285
|
+
};
|