math-exercises 3.0.74 → 3.0.75

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 (30) hide show
  1. package/lib/exercises/math/calcul/arithmetics/isInequalityTrue.js +2 -2
  2. package/lib/exercises/math/calcul/operations/operationsPrioritiesParenthesis.js +1 -1
  3. package/lib/exercises/math/calculLitteral/inequations/squareFunctionInequation.d.ts.map +1 -1
  4. package/lib/exercises/math/calculLitteral/inequations/squareFunctionInequation.js +15 -0
  5. package/lib/exercises/math/functions/affines/leadingCoefficientCalculV1.d.ts.map +1 -1
  6. package/lib/exercises/math/functions/affines/leadingCoefficientCalculV1.js +52 -0
  7. package/lib/exercises/math/functions/basics/inverseImageFunctionGeogebra.d.ts.map +1 -1
  8. package/lib/exercises/math/functions/basics/inverseImageFunctionGeogebra.js +24 -0
  9. package/lib/exercises/math/functions/parity/parityFromAlgebra.d.ts.map +1 -1
  10. package/lib/exercises/math/functions/parity/parityFromAlgebra.js +57 -2
  11. package/lib/exercises/math/geometry/euclidian/pythagoreOrThales.js +34 -31
  12. package/lib/exercises/math/geometry/thales/thalesCalcul.d.ts.map +1 -1
  13. package/lib/exercises/math/geometry/thales/thalesCalcul.js +79 -8
  14. package/lib/exercises/math/geometry/vectors/paralellismViaColinearity.d.ts.map +1 -1
  15. package/lib/exercises/math/geometry/vectors/paralellismViaColinearity.js +39 -1
  16. package/lib/exercises/math/geometry/vectors/parallelogramViaEqualVectors.d.ts.map +1 -1
  17. package/lib/exercises/math/geometry/vectors/parallelogramViaEqualVectors.js +32 -1
  18. package/lib/exercises/math/geometry/vectors/vectorLinearCombination.d.ts.map +1 -1
  19. package/lib/exercises/math/geometry/vectors/vectorLinearCombination.js +40 -2
  20. package/lib/exercises/math/probaStat/stats1var/choseReasoningForIndicator.d.ts.map +1 -1
  21. package/lib/exercises/math/probaStat/stats1var/choseReasoningForIndicator.js +17 -10
  22. package/lib/exercises/math/probaStat/stats1var/median.d.ts.map +1 -1
  23. package/lib/exercises/math/probaStat/stats1var/median.js +35 -0
  24. package/lib/exercises/math/probaStat/stats1var/medianList.d.ts.map +1 -1
  25. package/lib/exercises/math/probaStat/stats1var/medianList.js +18 -0
  26. package/lib/exercises/math/probaStat/stats1var/quartiles.d.ts.map +1 -1
  27. package/lib/exercises/math/probaStat/stats1var/quartiles.js +37 -0
  28. package/lib/exercises/math/probaStat/stats1var/quartilesList.d.ts.map +1 -1
  29. package/lib/exercises/math/probaStat/stats1var/quartilesList.js +23 -0
  30. package/package.json +1 -1
@@ -37,10 +37,10 @@ $$
37
37
  ${leftNode.toTex()} ${inequalitySign ? "<" : ">"} ${rightNode.toTex()}
38
38
  $$
39
39
 
40
- Cette inéquation est-elle vraie pour pour $x = ${x}$ ?`;
40
+ Cette inéquation est-elle vraie pour $x = ${x}$ ?`;
41
41
  };
42
42
  const getHint = (identifiers) => {
43
- return `Remplacer $x$ par $${identifiers.x}$ dans les deux membres. Ensuite, vérifie si l'inégalité est vraie ou non.`;
43
+ return `Remplace $x$ par $${identifiers.x}$ dans les deux membres. Ensuite, vérifie si l'inégalité est vraie ou non.`;
44
44
  };
45
45
  const reverseSign = (sign) => {
46
46
  let x = "";
@@ -86,7 +86,7 @@ const getOperationsPrioritiesParenthesisQuestion = () => {
86
86
  const isAdd2 = coinFlip();
87
87
  statement = new (isAdd ? AddNode : SubstractNode)(a.toTree(), new (isAdd2 ? AddNode : SubstractNode)(b.toTree(), new (isDivide ? DivideNode : MultiplyNode)(c.toTree(), d.toTree(), {
88
88
  forceTimesSign: true,
89
- }), { forceParenthesis: isAdd }));
89
+ }), { forceParenthesis: true }));
90
90
  break;
91
91
  }
92
92
  const identifiers = { nodeIds: statement.toIdentifiers(), type };
@@ -1 +1 @@
1
- {"version":3,"file":"squareFunctionInequation.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/calculLitteral/inequations/squareFunctionInequation.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAYT,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,gBAAgB,EAGjB,MAAM,sCAAsC,CAAC;AAY9C,KAAK,WAAW,GAAG;IACjB,CAAC,EAAE,MAAM,CAAC;IACV,gBAAgB,EAAE,gBAAgB,CAAC;CACpC,CAAC;AA0FF,eAAO,MAAM,wBAAwB,EAAE,QAAQ,CAAC,WAAW,CAa1D,CAAC"}
1
+ {"version":3,"file":"squareFunctionInequation.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/calculLitteral/inequations/squareFunctionInequation.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAcT,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,gBAAgB,EAGjB,MAAM,sCAAsC,CAAC;AAa9C,KAAK,WAAW,GAAG;IACjB,CAAC,EAAE,MAAM,CAAC;IACV,gBAAgB,EAAE,gBAAgB,CAAC;CACpC,CAAC;AA6GF,eAAO,MAAM,wBAAwB,EAAE,QAAQ,CAAC,WAAW,CAa1D,CAAC"}
@@ -30,6 +30,19 @@ $$
30
30
  x^2 ${inequationSymbol} ${k}
31
31
  $$`;
32
32
  };
33
+ // const getHint: GetHint<Identifiers> = (identifiers) => {
34
+ // return ``;
35
+ // };
36
+ // const getCorrection: GetCorrection<Identifiers> = (identifiers) => {
37
+ // const { k, inequationSymbol } = identifiers;
38
+ // return `On applique la fonction racine carrée à l'inégalité :
39
+ // ${alignTex([
40
+ // ["x^2", inequationSymbol, k.frenchify()],
41
+ // ["\\sqrt{x^2}", inequationSymbol, sqrt(k).toTex()],
42
+ // ["|x|", inequationSymbol, sqrt(k).simplify().toTex()],
43
+ // ])}
44
+ // `;
45
+ // };
33
46
  const getSquareFunctionInequationQuestion = () => {
34
47
  const k = coinFlip() ? randint(1, 11) ** 2 : randint(1, 100);
35
48
  const inequationSymbol = InequationSymbolConstructor.random();
@@ -43,6 +56,8 @@ const getQuestionFromIdentifiers = (identifiers) => {
43
56
  keys: ["S", "equal", "lbracket", "rbracket", "semicolon", "infty", "cup"],
44
57
  answerFormat: "tex",
45
58
  identifiers,
59
+ // hint: getHint(identifiers),
60
+ // correction: getCorrection(identifiers),
46
61
  };
47
62
  return question;
48
63
  };
@@ -1 +1 @@
1
- {"version":3,"file":"leadingCoefficientCalculV1.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/functions/affines/leadingCoefficientCalculV1.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAcT,MAAM,6BAA6B,CAAC;AAOrC,KAAK,WAAW,GAAG;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAiHF,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,WAAW,CAc5D,CAAC"}
1
+ {"version":3,"file":"leadingCoefficientCalculV1.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/functions/affines/leadingCoefficientCalculV1.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAgBT,MAAM,6BAA6B,CAAC;AASrC,KAAK,WAAW,GAAG;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAuKF,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,WAAW,CAe5D,CAAC"}
@@ -3,6 +3,8 @@ import { getDistinctQuestions } from "../../../../exercises/utils/getDistinctQue
3
3
  import { rationalVEA } from "../../../../exercises/vea/rationalVEA.js";
4
4
  import { Rational } from "../../../../math/numbers/rationals/rational.js";
5
5
  import { randint } from "../../../../math/utils/random/randint.js";
6
+ import { frac } from "../../../../tree/nodes/operators/fractionNode.js";
7
+ import { substract } from "../../../../tree/nodes/operators/substractNode.js";
6
8
  import { shuffle } from "../../../../utils/alea/shuffle.js";
7
9
  const getInstruction = (identifiers, opts) => {
8
10
  const { xA, yA, xB, yB } = identifiers;
@@ -42,6 +44,53 @@ const getLeadingCoefficientCalculV1Question = (opts) => {
42
44
  const identifiers = { xA, xB, yA, yB };
43
45
  return getQuestionFromIdentifiers(identifiers, opts);
44
46
  };
47
+ const getHint = (identifiers, opts) => {
48
+ const { xA, yA, xB, yB } = identifiers;
49
+ const usePoints = opts?.usePoints;
50
+ const useLinear = opts?.useLinear;
51
+ if (useLinear) {
52
+ if (usePoints) {
53
+ return `Pour déterminer le coefficient directeur $a$ d'une fonction linéaire à partir d'un point $A(x_A; y_A)$ de sa droite représentative, on utilise la formule :
54
+
55
+ $$
56
+ a = \\frac{y_A}{x_A}
57
+ $$`;
58
+ }
59
+ return `Pour déterminer le coefficient directeur $a$ d'une fonction linéaire $f$ à partir d'une image $f(x)$, on utilise la formule :
60
+
61
+ $$
62
+ a = \\frac{f(x)}{x}
63
+ $$`;
64
+ }
65
+ if (usePoints)
66
+ return `Pour déterminer le coefficient directeur $a$ d'une fonction affine à partir de deux points $A(x_A; y_A)$ et $B(x_B;y_B)$ de sa droite représentative, on utilise la formule :
67
+
68
+ $$
69
+ a = \\frac{y_B-y_A}{x_B-x_A}
70
+ $$`;
71
+ return `Pour déterminer le coefficient directeur $a$ d'une fonction affine $f$ à partir de deux images $f(x_1)$ et $f(x_2)$, on utilise la formule :
72
+
73
+ $$
74
+ a = \\frac{f(x_2)-f(x_1)}{x_2-x_1}
75
+ $$`;
76
+ };
77
+ const getCorrection = (identifiers, opts) => {
78
+ const { xA, yA, xB, yB } = identifiers;
79
+ const usePoints = opts?.usePoints;
80
+ const useLinear = opts?.useLinear;
81
+ if (useLinear) {
82
+ return `Le coefficient directeur $a$ est égal à :
83
+
84
+ $$
85
+ a = ${frac(yB, xB).toSimplificationTex()}
86
+ $$`;
87
+ }
88
+ return `Le coefficient directeur $a$ est égal à :
89
+
90
+ $$
91
+ a = ${frac(substract(yB, yA), substract(xB, xA)).toSimplificationTex()}
92
+ $$`;
93
+ };
45
94
  const getQuestionFromIdentifiers = (identifiers, opts) => {
46
95
  const question = {
47
96
  instruction: getInstruction(identifiers, opts),
@@ -50,6 +99,8 @@ const getQuestionFromIdentifiers = (identifiers, opts) => {
50
99
  answerFormat: "tex",
51
100
  keys: [],
52
101
  identifiers,
102
+ hint: getHint(identifiers, opts),
103
+ correction: getCorrection(identifiers, opts),
53
104
  };
54
105
  return question;
55
106
  };
@@ -97,4 +148,5 @@ export const leadingCoefficientCalculV1 = {
97
148
  subject: "Mathématiques",
98
149
  options,
99
150
  getQuestionFromIdentifiers,
151
+ hasHintAndCorrection: true,
100
152
  };
@@ -1 +1 @@
1
- {"version":3,"file":"inverseImageFunctionGeogebra.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/functions/basics/inverseImageFunctionGeogebra.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAaT,MAAM,6BAA6B,CAAC;AAmBrC,KAAK,WAAW,GAAG;IAEjB,MAAM,EAAE,MAAM,CAAC;IAIf,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;CACpB,CAAC;AAmNF,eAAO,MAAM,4BAA4B,EAAE,QAAQ,CAAC,WAAW,CAkB9D,CAAC"}
1
+ {"version":3,"file":"inverseImageFunctionGeogebra.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/functions/basics/inverseImageFunctionGeogebra.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAeT,MAAM,6BAA6B,CAAC;AAmBrC,KAAK,WAAW,GAAG;IAEjB,MAAM,EAAE,MAAM,CAAC;IAIf,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;CACpB,CAAC;AA6OF,eAAO,MAAM,4BAA4B,EAAE,QAAQ,CAAC,WAAW,CAmB9D,CAAC"}
@@ -152,6 +152,27 @@ const getInverseImageFunctionGeogebra = () => {
152
152
  };
153
153
  return getQuestionFromIdentifiers(identifiers);
154
154
  };
155
+ const getHint = (identifiers) => {
156
+ const { points, yValue } = identifiers;
157
+ return `Repère, s'il y en a, les points de la courbe qui ont pour ordonnée $${yValue}$. Les antécédents de $${yValue}$ sont alors les abscisses de ces points.`;
158
+ };
159
+ const getCorrection = (identifiers) => {
160
+ const { points, yValue } = identifiers;
161
+ const validPoints = points.filter((p) => p[1] === yValue);
162
+ const pts = validPoints.map((e) => new Point("A", e[0], e[1]));
163
+ if (!validPoints.length) {
164
+ return `Aucun point de la courbe n'a pour ordonnée $${yValue}$ : cela signifie que $${yValue}$ n'a pas d'antécédent par $f$.`;
165
+ }
166
+ return `On lit les points de la courbe qui ont pour ordonnée $${yValue}$ : ${validPoints.length === 1
167
+ ? `il n'y a que le point de coordonnées $${pts[0].toCoords()}$`
168
+ : `ce sont les points de coordonnées $${pts[0].toCoords()}$ et $${pts[1].toCoords()}$`}.
169
+
170
+ Les antécédents par $f$ de $${yValue}$ sont donc :
171
+
172
+ $$
173
+ ${getAnswer(identifiers)}
174
+ $$`;
175
+ };
155
176
  const getQuestionFromIdentifiers = (identifiers) => {
156
177
  const question = {
157
178
  instruction: getInstruction(identifiers),
@@ -160,6 +181,8 @@ const getQuestionFromIdentifiers = (identifiers) => {
160
181
  ggbOptions: getGGBOptions(identifiers),
161
182
  answerFormat: "tex",
162
183
  identifiers,
184
+ hint: getHint(identifiers),
185
+ correction: getCorrection(identifiers),
163
186
  };
164
187
  return question;
165
188
  };
@@ -218,4 +241,5 @@ export const inverseImageFunctionGeogebra = {
218
241
  getGGBOptions,
219
242
  getQuestionFromIdentifiers,
220
243
  rebuildIdentifiers,
244
+ hasHintAndCorrection: true,
221
245
  };
@@ -1 +1 @@
1
- {"version":3,"file":"parityFromAlgebra.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/functions/parity/parityFromAlgebra.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAYT,MAAM,6BAA6B,CAAC;AAYrC,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AA0HF,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,WAAW,CAanD,CAAC"}
1
+ {"version":3,"file":"parityFromAlgebra.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/functions/parity/parityFromAlgebra.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAcT,MAAM,6BAA6B,CAAC;AAerC,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAkLF,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,WAAW,CAcnD,CAAC"}
@@ -9,9 +9,18 @@ import { coinFlip } from "../../../../utils/alea/coinFlip.js";
9
9
  import { doWhile } from "../../../../utils/doWhile.js";
10
10
  import { probaFlip } from "../../../../utils/alea/probaFlip.js";
11
11
  import { probaLawFlip } from "../../../../utils/alea/probaLawFlip.js";
12
+ import { parseAlgebraic } from "../../../../tree/parsers/latexParser.js";
13
+ import { opposite } from "../../../../tree/nodes/functions/oppositeNode.js";
14
+ import { alignTex } from "../../../../utils/latex/alignTex.js";
12
15
  const getInstruction = (identifiers) => {
13
16
  const fct = identifiers.fctTex;
14
- return `Soit $f(x) = ${fct}$. La fonction $f$ est-elle paire, impaire, ou ni paire ni impaire ?`;
17
+ return `Soit $f$ la fonction définie par :
18
+
19
+ $$
20
+ f(x) = ${fct}
21
+ $$
22
+
23
+ La fonction $f$ est-elle paire, impaire, ou ni paire ni impaire ?`;
15
24
  };
16
25
  const getAnswer = (identifiers) => {
17
26
  const type = identifiers.type;
@@ -30,8 +39,10 @@ const getQuestionFromIdentifiers = (identifiers) => {
30
39
  answer: getAnswer(identifiers),
31
40
  instruction: getInstruction(identifiers),
32
41
  keys: [],
33
- answerFormat: "tex",
42
+ answerFormat: "raw",
34
43
  identifiers,
44
+ hint: getHint(identifiers),
45
+ correction: getCorrection(identifiers),
35
46
  };
36
47
  return question;
37
48
  };
@@ -104,6 +115,49 @@ const getParityFromAlgebraQuestion = () => {
104
115
  const identifiers = { type, fctTex: fct };
105
116
  return getQuestionFromIdentifiers(identifiers);
106
117
  };
118
+ const getHint = (identifiers) => {
119
+ return `Une fonction $f$ est paire si pour tout $x$ de son ensemble de définition, on a : $f(-x) = f(x)$.
120
+
121
+ Une fonction $f$ est impaire si pour tout $x$ de son ensemble de définition, on a : $f(-x) = -f(x)$.`;
122
+ };
123
+ const getCorrection = (identifiers) => {
124
+ const type = identifiers.type;
125
+ const fct = parseAlgebraic(identifiers.fctTex);
126
+ const fctEv = fct.toDetailedEvaluation({ x: opposite("x") });
127
+ const fctEvSimp = fctEv.simplify({ calculatePowers: true });
128
+ const fctEvIsSimplifiable = fctEv.toTex() !== fctEvSimp.toTex();
129
+ const oppFct = opposite(fct);
130
+ const oppFctSimp = oppFct.simplify({
131
+ calculatePowers: true,
132
+ towardsDistribute: true,
133
+ forbidFactorize: true,
134
+ });
135
+ const oppFctIsSimplifiable = oppFct.toTex() !== oppFctSimp.toTex();
136
+ return `On exprime $f(-x)$ :
137
+
138
+ ${alignTex([
139
+ ["f(-x)", "=", fctEv.toTex()],
140
+ ["", "=", fctEvSimp.toTex()],
141
+ ])}
142
+
143
+ ${type === "even"
144
+ ? "Puisque $f(-x) = f(x)$, la fonction $f$ est paire."
145
+ : `Puisque $f(-x)\\neq f(x)$, la fonction $f$ n'est pas paire.
146
+
147
+ On calcule alors $-f(x)$ :
148
+
149
+ ${alignTex([
150
+ ["-f(x)", "=", oppFct.toTex()],
151
+ oppFctIsSimplifiable ? ["", "=", oppFctSimp.toTex()] : [],
152
+ ])}`}
153
+
154
+ ${type === "uneven"
155
+ ? "Puisque $f(-x) = -f(x)$, la fonction $f$ est impaire."
156
+ : type === "neither"
157
+ ? "Puisque $f(-x)\\neq -f(x)$, la fonction $f$ n'est pas impaire. La fonction $f$ n'est donc ni paire, ni impaire."
158
+ : ""}
159
+ `;
160
+ };
107
161
  const getPropositions = (n, { answer }) => {
108
162
  const propositions = [];
109
163
  addValidProp(propositions, answer, "raw");
@@ -128,4 +182,5 @@ export const parityFromAlgebra = {
128
182
  answerType: "QCU",
129
183
  subject: "Mathématiques",
130
184
  getQuestionFromIdentifiers,
185
+ hasHintAndCorrection: true,
131
186
  };
@@ -55,37 +55,40 @@ const getInstruction = (identifiers) => {
55
55
 
56
56
  Pour ${instruction}, il faut utiliser... `;
57
57
  };
58
- // const getHint: GetHint<Identifiers> = (identifiers) => {
59
- // return `Voici les énoncés des théorèmes de Pythagore et de Thalès, et leurs réciproques :
60
- // - **Théorème de Pythagore** : Dans un triangle rectangle, le carré de l'hypoténuse est égal à la somme des carrés des deux autres côtés.
61
- // - **Réciproque du théorème de Pythagore** : Si dans un triangle, le carré de l'hypoténuse est égal à la somme des carrés des deux autres côtés, alors le triangle est rectangle.
62
- // - **Théorème de Thalès** : Soit un triangle $ABC$, et $D$ un point sur la droite $(AB)$ et $E$ un point sur la droite $(AC)$. Si les droites $(DE)$ et $(BC)$ sont parallèles, alors :
63
- // $$
64
- // \\frac{AD}{AB}=\\frac{AE}{AC}=\\frac{DE}{BC}
65
- // $$
66
- // - **Réciproque du théorème de Thalès** : Soit un triangle $ABC$, et $D$ un point sur la droite $(AB)$ et $E$ un point sur la droite $(AC)$. Si $\\frac{AD}{AB}=\\frac{AE}{AC}$, alors les droites $(AB)$ et $(AC)$ sont parallèles.`;
67
- // };
68
- // const getCorrection: GetCorrection<Identifiers> = (identifiers) => {
69
- // const { isAskingLength, pointsIdentifiers, isSegmentHeight } = identifiers;
70
- // const points = pointsIdentifiers.map((p) =>
71
- // PointConstructor.fromIdentifiers(p),
72
- // );
73
- // if (isSegmentHeight) {
74
- // if(isAskingLength){
75
- // // ("Pythagore");
76
- // return ``
77
- // } else {
78
- // // ("Recip pythagore");
79
- // }
80
- // } else {
81
- // if (isAskingLength) {
82
- // // ("Thales");
83
- // } else {
84
- // // ("Recip thales");
85
- // }
86
- // }
87
- // return ``;
88
- // };
58
+ const getHint = (identifiers) => {
59
+ return `Voici les énoncés des théorèmes de Pythagore et de Thalès, et leurs réciproques :
60
+
61
+ - **Théorème de Pythagore** : Dans un triangle rectangle, le carré de l'hypoténuse est égal à la somme des carrés des deux autres côtés.
62
+ - **Réciproque du théorème de Pythagore** : Si dans un triangle, le carré de l'hypoténuse est égal à la somme des carrés des deux autres côtés, alors le triangle est rectangle.
63
+ - **Théorème de Thalès** : Soit un triangle $ABC$, et $D$ un point sur la droite $(AB)$ et $E$ un point sur la droite $(AC)$. Si les droites $(DE)$ et $(BC)$ sont parallèles, alors :
64
+
65
+ $$
66
+ \\frac{AD}{AB}=\\frac{AE}{AC}=\\frac{DE}{BC}
67
+ $$
68
+ - **Réciproque du théorème de Thalès** : Soit un triangle $ABC$, et $D$ un point sur la droite $(AB)$ et $E$ un point sur la droite $(AC)$. Si $\\frac{AD}{AB}=\\frac{AE}{AC}$, alors les droites $(AB)$ et $(AC)$ sont parallèles.`;
69
+ };
70
+ const getCorrection = (identifiers) => {
71
+ const { isAskingLength, pointsIdentifiers, isSegmentHeight } = identifiers;
72
+ const points = pointsIdentifiers.map((p) => PointConstructor.fromIdentifiers(p));
73
+ if (isSegmentHeight) {
74
+ if (isAskingLength) {
75
+ // ("Pythagore");
76
+ return ``;
77
+ }
78
+ else {
79
+ // ("Recip pythagore");
80
+ }
81
+ }
82
+ else {
83
+ if (isAskingLength) {
84
+ // ("Thales");
85
+ }
86
+ else {
87
+ // ("Recip thales");
88
+ }
89
+ }
90
+ return ``;
91
+ };
89
92
  const getGGBOptions = (identifiers) => {
90
93
  const { isAskingLength, lengths, pointsIdentifiers, isSegmentHeight } = identifiers;
91
94
  const points = pointsIdentifiers.map((p) => PointConstructor.fromIdentifiers(p));
@@ -1 +1 @@
1
- {"version":3,"file":"thalesCalcul.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/geometry/thales/thalesCalcul.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAsBT,MAAM,6BAA6B,CAAC;AAMrC,OAAO,EAGL,mBAAmB,EACpB,MAAM,2CAA2C,CAAC;AAQnD,KAAK,WAAW,GAAG;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AAmJF,KAAK,OAAO,GAAG;IACb,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC;AAqEF,eAAO,MAAM,YAAY,EAAE,QAAQ,CAAC,WAAW,EAAE,OAAO,CAyBvD,CAAC"}
1
+ {"version":3,"file":"thalesCalcul.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/geometry/thales/thalesCalcul.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAsBT,MAAM,6BAA6B,CAAC;AAMrC,OAAO,EAGL,mBAAmB,EACpB,MAAM,2CAA2C,CAAC;AAanD,KAAK,WAAW,GAAG;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AA2OF,KAAK,OAAO,GAAG;IACb,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC;AAqEF,eAAO,MAAM,YAAY,EAAE,QAAQ,CAAC,WAAW,EAAE,OAAO,CA0BvD,CAAC"}
@@ -6,9 +6,14 @@ import { Segment } from "../../../../math/geometry/segment.js";
6
6
  import { Triangle, TriangleConstructor, } from "../../../../math/geometry/triangles/triangle.js";
7
7
  import { VectorConstructor } from "../../../../math/geometry/vector.js";
8
8
  import { randfloat } from "../../../../math/utils/random/randfloat.js";
9
+ import { randint } from "../../../../math/utils/random/randint.js";
9
10
  import { round } from "../../../../math/utils/round.js";
11
+ import { frac } from "../../../../tree/nodes/operators/fractionNode.js";
12
+ import { multiply } from "../../../../tree/nodes/operators/multiplyNode.js";
10
13
  import { coinFlip } from "../../../../utils/alea/coinFlip.js";
11
14
  import { random } from "../../../../utils/alea/random.js";
15
+ import { alignTex } from "../../../../utils/latex/alignTex.js";
16
+ import { approxOrEqual } from "../../../../utils/latex/approxOrEqual.js";
12
17
  import { randomLetter } from "../../../../utils/strings/randomLetter.js";
13
18
  const getSubTriangle = ({ triangle, insidePointsNames, ratio, isPapillon, }) => {
14
19
  const [A, B, C] = triangle.points;
@@ -25,7 +30,7 @@ const getPropositions = (n, { answer }) => {
25
30
  const propositions = [];
26
31
  addValidProp(propositions, answer);
27
32
  while (propositions.length < n) {
28
- tryToAddWrongProp(propositions, randfloat(3, 20, 1).frenchify());
33
+ tryToAddWrongProp(propositions, randfloat(3, 20, 2).frenchify());
29
34
  }
30
35
  return shuffleProps(propositions, n);
31
36
  };
@@ -65,12 +70,77 @@ On sait de plus que : ${allSides
65
70
  .map((e) => `$${e.toLengthTex()}$`)
66
71
  .join(" , ")}.
67
72
 
68
- Calculer $${segmentAskedName.slice(1, 3)}$ (arrondir aux dixième).`;
73
+ Calculer $${segmentAskedName.slice(1, 3)}$ (arrondir au centième).`;
74
+ };
75
+ const getHint = (identifiers) => {
76
+ const { triangleIdentifiers, insidePointsNames, ratio, isPapillon, segmentAskedName, } = identifiers;
77
+ const triangle = TriangleConstructor.fromIdentifiers(triangleIdentifiers);
78
+ const subTriangle = getSubTriangle({
79
+ triangle,
80
+ insidePointsNames: identifiers.insidePointsNames,
81
+ ratio,
82
+ isPapillon: identifiers.isPapillon,
83
+ });
84
+ const oppositeSegment = triangle.sides[2].toInsideName();
85
+ return `Puisque les droites $\\left(${subTriangle.sides[2].toInsideName()}\\right)$ et $\\left(${oppositeSegment}\\right)$ sont parallèles, d'après le théorème de Thalès, on a :
86
+
87
+ $$
88
+ \\frac{${triangle.sides[0].toInsideName()}}{${subTriangle.sides[0].toInsideName()}}=\\frac{${triangle.sides[1].toInsideName()}}{${subTriangle.sides[1].toInsideName()}}=\\frac{${triangle.sides[2].toInsideName()}}{${subTriangle.sides[2].toInsideName()}}
89
+ $$
90
+
91
+ Remplace dans cette égalité les longueurs par les valeurs données dans l'énoncé.
92
+ `;
93
+ };
94
+ const getCorrection = (identifiers) => {
95
+ const { triangleIdentifiers, insidePointsNames, ratio, isPapillon, segmentAskedName, } = identifiers;
96
+ const triangle = TriangleConstructor.fromIdentifiers(triangleIdentifiers);
97
+ const subTriangle = getSubTriangle({
98
+ triangle,
99
+ insidePointsNames: identifiers.insidePointsNames,
100
+ ratio,
101
+ isPapillon: identifiers.isPapillon,
102
+ });
103
+ const oppositeSegment = triangle.sides[2].toInsideName();
104
+ const ratios = [0, 1, 2].map((i) => [
105
+ triangle.sides[i],
106
+ subTriangle.sides[i],
107
+ ]);
108
+ const names = ratios.map((arr) => [
109
+ arr[0].toInsideName(),
110
+ arr[1].toInsideName(),
111
+ ]);
112
+ const lengths = ratios.map((arr) => [
113
+ arr[0].getLength().frenchify(),
114
+ arr[1].getLength().frenchify(),
115
+ ]);
116
+ const lengthAsked = segmentAskedName.slice(1, 3);
117
+ const lengthAskedColumn = names.findIndex((e) => e.some((s) => s === lengthAsked));
118
+ const lengthAskedRow = names[lengthAskedColumn].findIndex((s) => s === lengthAsked);
119
+ lengths[lengthAskedColumn][lengthAskedRow] = lengthAsked;
120
+ const chosenSecondColumn = randint(0, 3, [lengthAskedColumn]);
121
+ const fraction = frac(multiply(lengths[lengthAskedColumn][1 - lengthAskedRow].unfrenchify(), lengths[chosenSecondColumn][lengthAskedRow].unfrenchify()), lengths[chosenSecondColumn][1 - lengthAskedRow].unfrenchify());
122
+ const fracEv = fraction.evaluate();
123
+ return `Puisque les droites $\\left(${subTriangle.sides[2].toInsideName()}\\right)$ et $\\left(${oppositeSegment}\\right)$ sont parallèles, d'après le théorème de Thalès, on a :
124
+
125
+ $$
126
+ \\frac{${triangle.sides[0].toInsideName()}}{${subTriangle.sides[0].toInsideName()}}=\\frac{${triangle.sides[1].toInsideName()}}{${subTriangle.sides[1].toInsideName()}}=\\frac{${triangle.sides[2].toInsideName()}}{${subTriangle.sides[2].toInsideName()}}
127
+ $$
128
+
129
+ On remplace les longueurs par les valeurs données dans l'énoncé :
130
+
131
+ $$
132
+ ${[0, 1, 2].map((i) => `\\frac{${lengths[i][0]}}{${lengths[i][1]}}`).join("=")}
133
+ $$
134
+
135
+ Pour déterminer $${lengthAsked}$, on peut donc faire le calcul suivant :
136
+
137
+ ${alignTex([
138
+ [lengthAsked, "=", fraction.toTex()],
139
+ ["", ...approxOrEqual(fracEv, 2)],
140
+ ])}
141
+
142
+ `;
69
143
  };
70
- // const getHint : GetHint<Identifiers> = (identifiers)=>{
71
- // }
72
- // const getCorrection : GetCorrection<Identifiers> = (identifiers)=>{
73
- // }
74
144
  const getGGBOptions = (identifiers) => {
75
145
  const triangle = TriangleConstructor.fromIdentifiers(identifiers.triangleIdentifiers);
76
146
  const subTriangle = getSubTriangle({
@@ -164,8 +234,8 @@ const getQuestionFromIdentifiers = (identifiers, opts) => {
164
234
  keys: getKeys(identifiers, opts),
165
235
  answerFormat: "tex",
166
236
  identifiers,
167
- // hint: getHint(identifiers),
168
- // correction: getCorrection(identifiers),
237
+ hint: getHint(identifiers),
238
+ correction: getCorrection(identifiers),
169
239
  ggbOptions: getGGBOptions(identifiers, opts),
170
240
  };
171
241
  return question;
@@ -194,4 +264,5 @@ export const thalesCalcul = {
194
264
  };
195
265
  },
196
266
  getQuestionFromIdentifiers,
267
+ hasHintAndCorrection: true,
197
268
  };
@@ -1 +1 @@
1
- {"version":3,"file":"paralellismViaColinearity.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/geometry/vectors/paralellismViaColinearity.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAYT,MAAM,6BAA6B,CAAC;AAarC,KAAK,WAAW,GAAG;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAsFF,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,WAAW,CAY3D,CAAC"}
1
+ {"version":3,"file":"paralellismViaColinearity.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/geometry/vectors/paralellismViaColinearity.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAcT,MAAM,6BAA6B,CAAC;AAgBrC,KAAK,WAAW,GAAG;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AA4HF,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,WAAW,CAa3D,CAAC"}
@@ -2,9 +2,10 @@ import { addValidProp, tryToAddWrongProp, } from "../../../../exercises/exercise
2
2
  import { getDistinctQuestions } from "../../../../exercises/utils/getDistinctQuestions.js";
3
3
  import { Line } from "../../../../math/geometry/line.js";
4
4
  import { Point, PointConstructor } from "../../../../math/geometry/point.js";
5
- import { VectorConstructor } from "../../../../math/geometry/vector.js";
5
+ import { Vector, VectorConstructor } from "../../../../math/geometry/vector.js";
6
6
  import { randint } from "../../../../math/utils/random/randint.js";
7
7
  import { NumberNode } from "../../../../tree/nodes/numbers/numberNode.js";
8
+ import { substract, } from "../../../../tree/nodes/operators/substractNode.js";
8
9
  import { coinFlip } from "../../../../utils/alea/coinFlip.js";
9
10
  import { shuffle } from "../../../../utils/alea/shuffle.js";
10
11
  const getInstruction = (identifiers) => {
@@ -27,6 +28,40 @@ const getAnswer = (identifiers) => {
27
28
  const answer = isParallele ? "Oui" : "Non";
28
29
  return answer;
29
30
  };
31
+ const getHint = (identifiers) => {
32
+ return `Les droites $(AB)$ et $(CD)$ sont parallèles si et seulement si les vecteurs $\\overrightarrow{AB}$ et $\\overrightarrow{CD}$ sont colinéaires. Calcule donc les coordonnées puis le déterminant des vecteurs $\\overrightarrow{AB}$ et $\\overrightarrow{CD}$.`;
33
+ };
34
+ const getCorrection = (identifiers) => {
35
+ const A = new Point("A", identifiers.xA, identifiers.yA);
36
+ const B = new Point("B", identifiers.xB, identifiers.yB);
37
+ const C = new Point("C", identifiers.xC, identifiers.yC);
38
+ const D = new Point("D", identifiers.xD, identifiers.yD);
39
+ const vec1 = new Vector("AB", substract(B.x, A.x), substract(B.y, A.y));
40
+ const vec2 = new Vector("CD", substract(D.x, C.x), substract(D.y, C.y));
41
+ const vec1Simp = vec1.simplify();
42
+ const vec2Simp = vec2.simplify();
43
+ const det = vec1Simp.determinant(vec2Simp);
44
+ const isParallel = vec1.isColinear(vec2);
45
+ return `Les droites $(AB)$ et $(CD)$ sont parallèles si et seulement si les vecteurs $\\overrightarrow{AB}$ et $\\overrightarrow{CD}$ sont colinéaires. On calcule donc d'abord les coordonnées de ces vecteurs :
46
+
47
+ $$
48
+ ${vec1.toTexWithCoords()}=${vec1Simp.toBinomCoords().toTex()}
49
+ $$
50
+
51
+ $$
52
+ ${vec2.toTexWithCoords()}=${vec2Simp.toBinomCoords().toTex()}
53
+ $$
54
+
55
+ Puis, on calcule le déterminant des vecteurs $\\overrightarrow{AB}$ et $\\overrightarrow{CD}$ :
56
+
57
+ $$
58
+ \\det(${vec1.toTex()};${vec2.toTex()})=${det.toTex()}=${det.simplify().toTex()}
59
+ $$
60
+
61
+ ${isParallel
62
+ ? `Puisque le déterminant est nul, les vecteurs sont colinéaires. Les droites $(AB)$ et $(CD)$ sont donc parallèles.`
63
+ : `Puisque le déterminant n'est pas nul, les vecteurs ne sont pas colinéaires. Les droites $(AB)$ et $(CD)$ ne sont donc pas parallèles.`}`;
64
+ };
30
65
  const getQuestionFromIdentifiers = (identifiers) => {
31
66
  const question = {
32
67
  answer: getAnswer(identifiers),
@@ -34,6 +69,8 @@ const getQuestionFromIdentifiers = (identifiers) => {
34
69
  keys: [],
35
70
  answerFormat: "raw",
36
71
  identifiers,
72
+ hint: getHint(identifiers),
73
+ correction: getCorrection(identifiers),
37
74
  };
38
75
  return question;
39
76
  };
@@ -92,4 +129,5 @@ export const paralellismViaColinearity = {
92
129
  answerType: "QCU",
93
130
  subject: "Mathématiques",
94
131
  getQuestionFromIdentifiers,
132
+ hasHintAndCorrection: true,
95
133
  };
@@ -1 +1 @@
1
- {"version":3,"file":"parallelogramViaEqualVectors.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/geometry/vectors/parallelogramViaEqualVectors.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAYT,MAAM,6BAA6B,CAAC;AAWrC,KAAK,WAAW,GAAG;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AA6EF,eAAO,MAAM,4BAA4B,EAAE,QAAQ,CAAC,WAAW,CAY9D,CAAC"}
1
+ {"version":3,"file":"parallelogramViaEqualVectors.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/geometry/vectors/parallelogramViaEqualVectors.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAcT,MAAM,6BAA6B,CAAC;AAcrC,KAAK,WAAW,GAAG;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AA4GF,eAAO,MAAM,4BAA4B,EAAE,QAAQ,CAAC,WAAW,CAa9D,CAAC"}
@@ -1,7 +1,8 @@
1
1
  import { addValidProp, tryToAddWrongProp, } from "../../../../exercises/exercise.js";
2
2
  import { getDistinctQuestions } from "../../../../exercises/utils/getDistinctQuestions.js";
3
3
  import { Point, PointConstructor } from "../../../../math/geometry/point.js";
4
- import { VectorConstructor } from "../../../../math/geometry/vector.js";
4
+ import { Vector, VectorConstructor } from "../../../../math/geometry/vector.js";
5
+ import { substract, } from "../../../../tree/nodes/operators/substractNode.js";
5
6
  import { coinFlip } from "../../../../utils/alea/coinFlip.js";
6
7
  import { shuffle } from "../../../../utils/alea/shuffle.js";
7
8
  const getInstruction = (identifiers) => {
@@ -24,6 +25,33 @@ const getAnswer = (identifiers) => {
24
25
  const answer = isParallelogram ? "Oui" : "Non";
25
26
  return answer;
26
27
  };
28
+ const getHint = (identifiers) => {
29
+ return `$ABCD$ est un parallélogramme si et seulement si les vecteurs $\\overrightarrow{AB}$ et $\\overrightarrow{DC}$ sont égaux.`;
30
+ };
31
+ const getCorrection = (identifiers) => {
32
+ const A = new Point("A", identifiers.xA, identifiers.yA);
33
+ const B = new Point("B", identifiers.xB, identifiers.yB);
34
+ const C = new Point("C", identifiers.xC, identifiers.yC);
35
+ const D = new Point("D", identifiers.xD, identifiers.yD);
36
+ const vec1 = new Vector("AB", substract(B.x, A.x), substract(B.y, A.y));
37
+ const vec2 = new Vector("DC", substract(C.x, D.x), substract(C.y, D.y));
38
+ const vec1Simp = vec1.simplify();
39
+ const vec2Simp = vec2.simplify();
40
+ const isParallelogram = vec1Simp.equals(vec2Simp);
41
+ return `$ABCD$ est un parallélogramme si et seulement si les vecteurs $\\overrightarrow{AB}$ et $\\overrightarrow{DC}$ sont égaux. On calcule donc les coordonnées de ces vecteurs :
42
+
43
+ $$
44
+ ${vec1.toTexWithCoords()}=${vec1Simp.toBinomCoords().toTex()}
45
+ $$
46
+
47
+ $$
48
+ ${vec2.toTexWithCoords()}=${vec2Simp.toBinomCoords().toTex()}
49
+ $$
50
+
51
+ ${isParallelogram
52
+ ? `Puisque les vecteurs sont égaux, $ABCD$ est un parallélogramme.`
53
+ : `Puisque les vecteurs ne sont pas égaux, $ABCD$ n'est pas un parallélogramme.`}`;
54
+ };
27
55
  const getQuestionFromIdentifiers = (identifiers) => {
28
56
  const question = {
29
57
  answer: getAnswer(identifiers),
@@ -31,6 +59,8 @@ const getQuestionFromIdentifiers = (identifiers) => {
31
59
  keys: [],
32
60
  answerFormat: "raw",
33
61
  identifiers,
62
+ hint: getHint(identifiers),
63
+ correction: getCorrection(identifiers),
34
64
  };
35
65
  return question;
36
66
  };
@@ -82,4 +112,5 @@ export const parallelogramViaEqualVectors = {
82
112
  answerType: "QCU",
83
113
  subject: "Mathématiques",
84
114
  getQuestionFromIdentifiers,
115
+ hasHintAndCorrection: true,
85
116
  };
@@ -1 +1 @@
1
- {"version":3,"file":"vectorLinearCombination.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/geometry/vectors/vectorLinearCombination.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAYT,MAAM,6BAA6B,CAAC;AASrC,KAAK,WAAW,GAAG;IACjB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,YAAY,CAAC;IAChB,CAAC,EAAE,YAAY,CAAC;CACjB,CAAC;AAEF,KAAK,YAAY,GAAG;IAClB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX,CAAC;AAmJF,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,WAAW,CAazD,CAAC"}
1
+ {"version":3,"file":"vectorLinearCombination.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/geometry/vectors/vectorLinearCombination.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAcT,MAAM,6BAA6B,CAAC;AAYrC,KAAK,WAAW,GAAG;IACjB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,YAAY,CAAC;IAChB,CAAC,EAAE,YAAY,CAAC;CACjB,CAAC;AAEF,KAAK,YAAY,GAAG;IAClB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX,CAAC;AAyMF,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,WAAW,CAczD,CAAC"}
@@ -3,8 +3,8 @@ import { getDistinctQuestions } from "../../../../exercises/utils/getDistinctQue
3
3
  import { Vector, VectorConstructor } from "../../../../math/geometry/vector.js";
4
4
  import { randint } from "../../../../math/utils/random/randint.js";
5
5
  import { NumberNode } from "../../../../tree/nodes/numbers/numberNode.js";
6
- import { AddNode } from "../../../../tree/nodes/operators/addNode.js";
7
- import { MultiplyNode } from "../../../../tree/nodes/operators/multiplyNode.js";
6
+ import { add, AddNode } from "../../../../tree/nodes/operators/addNode.js";
7
+ import { multiply, MultiplyNode, } from "../../../../tree/nodes/operators/multiplyNode.js";
8
8
  import { VariableNode } from "../../../../tree/nodes/variables/variableNode.js";
9
9
  const getInstruction = (identifiers) => {
10
10
  const { a, b } = identifiers;
@@ -26,6 +26,41 @@ const getAnswer = (identifiers) => {
26
26
  const correctAnswer = new Vector("au+bv", aUPlusBv.x, aUPlusBv.y);
27
27
  return `${correctAnswer.toInlineCoordsTex()}`;
28
28
  };
29
+ const getHint = (identifiers) => {
30
+ return `Calcule d'abord les coordonnées de chaque vecteur de la somme. Puis, additionne ces coordonnées.`;
31
+ };
32
+ const getCorrection = (identifiers) => {
33
+ const { a, b, u, v } = identifiers;
34
+ const uVec = new Vector("u", u.x.toTree(), u.y.toTree());
35
+ const coeffedU = new Vector("au", multiply(a, uVec.x), multiply(a, uVec.y));
36
+ const vVec = new Vector("v", v.x.toTree(), v.y.toTree());
37
+ const coeffedV = new Vector("bv", multiply(b, vVec.x), multiply(b, vVec.y));
38
+ const sum = add(multiply(a, "\\overrightarrow{u}"), multiply(b, "\\overrightarrow{v}")).toTex();
39
+ const sumVec = new Vector("sum", add(coeffedU.x.simplify(), coeffedV.x.simplify()), add(coeffedU.y.simplify(), coeffedV.y.simplify()));
40
+ return `${a !== 1
41
+ ? `Les coordonnées du vecteur $${multiply(a, "\\overrightarrow{u}").toTex()}$ sont :
42
+
43
+ $$
44
+ ${coeffedU.toCoords()} = ${coeffedU.simplify().toCoords()}
45
+ $$`
46
+ : ""}
47
+
48
+ ${a !== 1
49
+ ? `Les coordonnées du vecteur $${multiply(b, "\\overrightarrow{v}").toTex()}$ sont :
50
+
51
+ $$
52
+ ${coeffedV.toCoords()} = ${coeffedV.simplify().toCoords()}
53
+ $$`
54
+ : ""}
55
+
56
+ En additionnant, on obtient donc les coordonnées du vecteur $${sum}$ :
57
+
58
+ $$
59
+ ${sumVec.toCoords()} = ${sumVec.simplify().toCoords()}
60
+ $$
61
+
62
+ `;
63
+ };
29
64
  const getQuestionFromIdentifiers = (identifiers) => {
30
65
  const question = {
31
66
  answer: getAnswer(identifiers),
@@ -33,6 +68,8 @@ const getQuestionFromIdentifiers = (identifiers) => {
33
68
  keys: ["semicolon"],
34
69
  answerFormat: "tex",
35
70
  identifiers,
71
+ hint: getHint(identifiers),
72
+ correction: getCorrection(identifiers),
36
73
  };
37
74
  return question;
38
75
  };
@@ -112,4 +149,5 @@ export const vectorLinearCombination = {
112
149
  isAnswerValid,
113
150
  subject: "Mathématiques",
114
151
  getQuestionFromIdentifiers,
152
+ hasHintAndCorrection: true,
115
153
  };
@@ -1 +1 @@
1
- {"version":3,"file":"choseReasoningForIndicator.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/probaStat/stats1var/choseReasoningForIndicator.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAeT,MAAM,6BAA6B,CAAC;AAUrC,KAAK,WAAW,GAAG;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAqHF,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,WAAW,CAa5D,CAAC"}
1
+ {"version":3,"file":"choseReasoningForIndicator.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/probaStat/stats1var/choseReasoningForIndicator.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAeT,MAAM,6BAA6B,CAAC;AAUrC,KAAK,WAAW,GAAG;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAgIF,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,WAAW,CAa5D,CAAC"}
@@ -38,13 +38,20 @@ La ${indicatorAsked} de cette série est $${avg}$.
38
38
 
39
39
  Quelle est la justification correcte ?`;
40
40
  };
41
- // const getHint: GetHint<Identifiers> = (identifiers) => {
42
- // const { values, indicatorAsked } = identifiers;
43
- // return indicatorAsked === "moyenne" ? `La moyenne est la somme des valeurs, divisée par le nombre de valeurs.` : `La médiane est la valeur telle qu'il y a autant de valeurs inférieures à elle que de valeurs supérieures.`;
44
- // };
45
- // const getCorrection: GetCorrection<Identifiers> = (identifiers) => {
46
- // return ``
47
- // };
41
+ const getHint = (identifiers) => {
42
+ const { values, indicatorAsked } = identifiers;
43
+ return indicatorAsked === "moyenne"
44
+ ? `La moyenne est la somme des valeurs, divisée par le nombre de valeurs.`
45
+ : `La médiane est la valeur centrale de la série.`;
46
+ };
47
+ const getCorrection = (identifiers) => {
48
+ const { values, indicatorAsked } = identifiers;
49
+ return indicatorAsked === "moyenne"
50
+ ? `La moyenne est la somme des valeurs, divisée par le nombre de valeurs. Ici, ${getAnswer(identifiers).toLocaleLowerCase()}.
51
+ `
52
+ : `La médiane est la valeur centrale de la série : c'est à dire qu'il y a autant de valeurs inférieures à elle que de valeurs supérieures. Ici, ${getAnswer(identifiers).toLocaleLowerCase()}.
53
+ `;
54
+ };
48
55
  const getChoseReasoningForIndicatorQuestion = (ops) => {
49
56
  const max = 2 * randint(5, 20);
50
57
  const x = max / 2;
@@ -77,8 +84,8 @@ const getQuestionFromIdentifiers = (identifiers) => {
77
84
  instruction: getInstruction(identifiers),
78
85
  answerFormat: "raw",
79
86
  identifiers,
80
- // hint: getHint(identifiers),
81
- // correction: getCorrection(identifiers),
87
+ hint: getHint(identifiers),
88
+ correction: getCorrection(identifiers),
82
89
  };
83
90
  return question;
84
91
  };
@@ -93,5 +100,5 @@ export const choseReasoningForIndicator = {
93
100
  subject: "Mathématiques",
94
101
  answerType: "QCU",
95
102
  getQuestionFromIdentifiers,
96
- // hasHintAndCorrection: true
103
+ hasHintAndCorrection: true,
97
104
  };
@@ -1 +1 @@
1
- {"version":3,"file":"median.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/probaStat/stats1var/median.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,QAAQ,EAWT,MAAM,sBAAsB,CAAC;AAG9B,KAAK,WAAW,GAAG;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B,CAAC;AAmFF,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,WAAW,CAYjD,CAAC"}
1
+ {"version":3,"file":"median.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/probaStat/stats1var/median.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,QAAQ,EAaT,MAAM,sBAAsB,CAAC;AAG9B,KAAK,WAAW,GAAG;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B,CAAC;AAuHF,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,WAAW,CAajD,CAAC"}
@@ -36,6 +36,38 @@ const getMedianWithTable = () => {
36
36
  const identifiers = { randomValues, randomEffectives };
37
37
  return getQuestionFromIdentifiers(identifiers);
38
38
  };
39
+ const getHint = (identifiers) => {
40
+ return `Dresse le tableau des effectifs cumulés croissants. Cela permet de trouver l'effectif total $N$. Puis :
41
+
42
+ - Si $N$ est pair, alors la médiane est la valeur comprise entre la valeur de rang $\\frac{N}{2}$ et celle de rang $\\frac{N}{2}+1$;
43
+ - Si $N$ est impair, alors la médiane est la valeur de rang $\\frac{N+1}{2}$.`;
44
+ };
45
+ const getCorrection = (identifiers) => {
46
+ const { randomEffectives, randomValues } = identifiers;
47
+ const eccs = [];
48
+ let s = 0;
49
+ for (let i = 0; i < randomEffectives.length; i++) {
50
+ s += randomEffectives[i];
51
+ eccs.push(s);
52
+ }
53
+ const total = eccs[eccs.length - 1];
54
+ const rank = total / 2;
55
+ return `On dresse le tableau des effectifs cumulés croissants (ECC) :
56
+
57
+ ${mdTable([
58
+ ["Valeur", ...randomValues.map((e) => dollarize(e))],
59
+ ["Effectif", ...randomEffectives.map((e) => dollarize(e))],
60
+ ["ECC", ...eccs.map((e) => dollarize(e))],
61
+ ])}
62
+
63
+ L'effectif total est donc $${total}$.
64
+
65
+ Puisque $\\frac{${total}}{2} = ${rank.frenchify()}$, la médiane est ${rank % 1 === 0
66
+ ? `entre la $${rank}$ème et la $${rank + 1}$ème valeur.`
67
+ : `la $${Math.ceil(rank)}$ème valeur.`}
68
+
69
+ La médiane est donc $${getAnswer(identifiers)}$.`;
70
+ };
39
71
  const getQuestionFromIdentifiers = (identifiers) => {
40
72
  const question = {
41
73
  instruction: getInstruction(identifiers),
@@ -44,6 +76,8 @@ const getQuestionFromIdentifiers = (identifiers) => {
44
76
  answerFormat: "tex",
45
77
  identifiers,
46
78
  style: { tableHasNoHeader: true },
79
+ hint: getHint(identifiers),
80
+ correction: getCorrection(identifiers),
47
81
  };
48
82
  return question;
49
83
  };
@@ -70,4 +104,5 @@ export const medianWithTable = {
70
104
  isAnswerValid,
71
105
  subject: "Mathématiques",
72
106
  getQuestionFromIdentifiers,
107
+ hasHintAndCorrection: true,
73
108
  };
@@ -1 +1 @@
1
- {"version":3,"file":"medianList.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/probaStat/stats1var/medianList.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,QAAQ,EAYT,MAAM,sBAAsB,CAAC;AAE9B,KAAK,WAAW,GAAG;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB,CAAC;AA+DF,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,WAAW,CAYhD,CAAC"}
1
+ {"version":3,"file":"medianList.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/probaStat/stats1var/medianList.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,QAAQ,EAcT,MAAM,sBAAsB,CAAC;AAE9B,KAAK,WAAW,GAAG;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB,CAAC;AAkFF,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,WAAW,CAahD,CAAC"}
@@ -25,6 +25,21 @@ const getMedianList = () => {
25
25
  const identifiers = { sortedValues };
26
26
  return getQuestionFromIdentifiers(identifiers);
27
27
  };
28
+ const getHint = (identifiers) => {
29
+ return `La médiane est la valeur centrale de la série : il y a autant de valeur inférieures à la médiane que de valeurs supérieures à la médiane.`;
30
+ };
31
+ const getCorrection = (identifiers) => {
32
+ const { sortedValues } = identifiers;
33
+ const total = sortedValues.length;
34
+ const rank = total / 2;
35
+ return `Il y a $${total}$ valeurs dans la liste.
36
+
37
+ Puisque $\\frac{${total}}{2} = ${rank.frenchify()}$, la médiane est ${rank % 1 === 0
38
+ ? `entre la $${rank}$ème et la $${rank + 1}$ème valeur.`
39
+ : `la $${Math.ceil(rank)}$ème valeur.`}
40
+
41
+ La médiane est donc $${getAnswer(identifiers)}$.`;
42
+ };
28
43
  const getQuestionFromIdentifiers = (identifiers) => {
29
44
  const question = {
30
45
  instruction: getInstruction(identifiers),
@@ -32,6 +47,8 @@ const getQuestionFromIdentifiers = (identifiers) => {
32
47
  keys: [],
33
48
  answerFormat: "tex",
34
49
  identifiers,
50
+ hint: getHint(identifiers),
51
+ correction: getCorrection(identifiers),
35
52
  };
36
53
  return question;
37
54
  };
@@ -59,4 +76,5 @@ export const medianWithList = {
59
76
  isAnswerValid,
60
77
  subject: "Mathématiques",
61
78
  getQuestionFromIdentifiers,
79
+ hasHintAndCorrection: true,
62
80
  };
@@ -1 +1 @@
1
- {"version":3,"file":"quartiles.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/probaStat/stats1var/quartiles.ts"],"names":[],"mappings":"AASA,OAAO,EACL,QAAQ,EAWT,MAAM,sBAAsB,CAAC;AAG9B,KAAK,WAAW,GAAG;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAsFF,eAAO,MAAM,SAAS,EAAE,QAAQ,CAAC,WAAW,CAY3C,CAAC"}
1
+ {"version":3,"file":"quartiles.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/probaStat/stats1var/quartiles.ts"],"names":[],"mappings":"AAYA,OAAO,EACL,QAAQ,EAaT,MAAM,sBAAsB,CAAC;AAG9B,KAAK,WAAW,GAAG;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AA6HF,eAAO,MAAM,SAAS,EAAE,QAAQ,CAAC,WAAW,CAa3C,CAAC"}
@@ -1,5 +1,7 @@
1
1
  import { randint } from "../../../../math/utils/random/randint.js";
2
2
  import { firstQuartile, thirdQuartile, } from "../../../../math/utils/stats/quartiles.js";
3
+ import { frac } from "../../../../tree/nodes/operators/fractionNode.js";
4
+ import { multiply } from "../../../../tree/nodes/operators/multiplyNode.js";
3
5
  import { shuffle } from "../../../../utils/alea/shuffle.js";
4
6
  import { dollarize } from "../../../../utils/latex/dollarize.js";
5
7
  import { mdTable } from "../../../../utils/markdown/mdTable.js";
@@ -41,6 +43,38 @@ const getQuartiles = () => {
41
43
  const identifiers = { randomValues, randomEffectives, randomQuartile };
42
44
  return getQuestionFromIdentifiers(identifiers);
43
45
  };
46
+ const getHint = (identifiers) => {
47
+ const { randomEffectives, randomValues, randomQuartile } = identifiers;
48
+ if (randomQuartile === 0)
49
+ return `Le premier quartile est la valeur de la série telle qu'au moins un quart des valeurs lui sont inférieures. Dresse le tableau des effectifs cumulés croissants de la série, puis calcule ce que vaut un quart de l'effectif total.`;
50
+ return `Le troisième quartile est la valeur de la série telle qu'au moins un trois quarts des valeurs lui sont inférieures. Dresse le tableau des effectifs cumulés croissants de la série, puis calcule ce que vaut un trois quarts de l'effectif total.`;
51
+ };
52
+ const getCorrection = (identifiers) => {
53
+ const { randomEffectives, randomValues, randomQuartile } = identifiers;
54
+ const eccs = [];
55
+ let s = 0;
56
+ for (let i = 0; i < randomEffectives.length; i++) {
57
+ s += randomEffectives[i];
58
+ eccs.push(s);
59
+ }
60
+ const total = eccs[eccs.length - 1];
61
+ const rank = randomQuartile === 0 ? frac(total, 4) : frac(multiply(3, total), 4);
62
+ const rankEv = rank.evaluate();
63
+ const numeral = randomQuartile === 0 ? "premier" : "troisième";
64
+ return `On dresse le tableau des effectifs cumulés croissants (ECC) :
65
+
66
+ ${mdTable([
67
+ ["Valeur", ...randomValues.map((e) => dollarize(e))],
68
+ ["Effectif", ...randomEffectives.map((e) => dollarize(e))],
69
+ ["ECC", ...eccs.map((e) => dollarize(e))],
70
+ ])}
71
+
72
+ L'effectif total est donc $${total}$.
73
+
74
+ Puisque $${rank.toTex()} = ${rankEv.frenchify()}$, le ${numeral} quartile est la $${Math.ceil(rankEv)}$-ème valeur.
75
+
76
+ Le ${numeral} quartile est donc $${getAnswer(identifiers)}$.`;
77
+ };
44
78
  const getQuestionFromIdentifiers = (identifiers) => {
45
79
  const question = {
46
80
  instruction: getInstruction(identifiers),
@@ -49,6 +83,8 @@ const getQuestionFromIdentifiers = (identifiers) => {
49
83
  answerFormat: "tex",
50
84
  identifiers,
51
85
  style: { tableHasNoHeader: true },
86
+ hint: getHint(identifiers),
87
+ correction: getCorrection(identifiers),
52
88
  };
53
89
  return question;
54
90
  };
@@ -75,4 +111,5 @@ export const quartiles = {
75
111
  isAnswerValid,
76
112
  subject: "Mathématiques",
77
113
  getQuestionFromIdentifiers,
114
+ hasHintAndCorrection: true,
78
115
  };
@@ -1 +1 @@
1
- {"version":3,"file":"quartilesList.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/probaStat/stats1var/quartilesList.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,QAAQ,EAYT,MAAM,sBAAsB,CAAC;AAG9B,KAAK,WAAW,GAAG;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAuEF,eAAO,MAAM,aAAa,EAAE,QAAQ,CAAC,WAAW,CAY/C,CAAC"}
1
+ {"version":3,"file":"quartilesList.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/probaStat/stats1var/quartilesList.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,QAAQ,EAcT,MAAM,sBAAsB,CAAC;AAG9B,KAAK,WAAW,GAAG;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAgGF,eAAO,MAAM,aAAa,EAAE,QAAQ,CAAC,WAAW,CAa/C,CAAC"}
@@ -1,5 +1,7 @@
1
1
  import { randint } from "../../../../math/utils/random/randint.js";
2
2
  import { firstQuartile, thirdQuartile, } from "../../../../math/utils/stats/quartiles.js";
3
+ import { frac } from "../../../../tree/nodes/operators/fractionNode.js";
4
+ import { multiply } from "../../../../tree/nodes/operators/multiplyNode.js";
3
5
  import { addValidProp, shuffleProps, tryToAddWrongProp, } from "../../../exercise.js";
4
6
  import { getDistinctQuestions } from "../../../utils/getDistinctQuestions.js";
5
7
  const getInstruction = ({ randomQuartile, randomValues, }) => {
@@ -34,6 +36,24 @@ const getQuartiles = () => {
34
36
  };
35
37
  return getQuestionFromIdentifiers(identifiers);
36
38
  };
39
+ const getHint = (identifiers) => {
40
+ const { randomValues, randomQuartile } = identifiers;
41
+ if (randomQuartile === 0)
42
+ return `Le premier quartile est la valeur de la série telle qu'au moins un quart des valeurs lui sont inférieures. `;
43
+ return `Le troisième quartile est la valeur de la série telle qu'au moins un trois quarts des valeurs lui sont inférieures.`;
44
+ };
45
+ const getCorrection = (identifiers) => {
46
+ const { randomValues, randomQuartile } = identifiers;
47
+ const total = randomValues.length;
48
+ const rank = randomQuartile === 0 ? frac(total, 4) : frac(multiply(3, total), 4);
49
+ const rankEv = rank.evaluate();
50
+ const numeral = randomQuartile === 0 ? "premier" : "troisième";
51
+ return `Il y a $${total}$ valeurs dans la série.
52
+
53
+ Puisque $${rank.toTex()} = ${rankEv.frenchify()}$, le ${numeral} quartile est la $${Math.ceil(rankEv)}$-ème valeur.
54
+
55
+ Le ${numeral} quartile est donc $${getAnswer(identifiers)}$.`;
56
+ };
37
57
  const getQuestionFromIdentifiers = (identifiers) => {
38
58
  const question = {
39
59
  instruction: getInstruction(identifiers),
@@ -41,6 +61,8 @@ const getQuestionFromIdentifiers = (identifiers) => {
41
61
  keys: [],
42
62
  answerFormat: "tex",
43
63
  identifiers,
64
+ hint: getHint(identifiers),
65
+ correction: getCorrection(identifiers),
44
66
  };
45
67
  return question;
46
68
  };
@@ -71,4 +93,5 @@ export const quartilesList = {
71
93
  isAnswerValid,
72
94
  subject: "Mathématiques",
73
95
  getQuestionFromIdentifiers,
96
+ hasHintAndCorrection: true,
74
97
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "math-exercises",
3
3
  "type": "module",
4
- "version": "3.0.74",
4
+ "version": "3.0.75",
5
5
  "description": "Math exercises generator for middle school and high school",
6
6
  "main": "lib/index.js",
7
7
  "files": [