math-exercises 3.0.149 → 3.0.150
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/exercises/math/scratch/index.d.ts +13 -0
- package/lib/exercises/math/scratch/index.d.ts.map +1 -1
- package/lib/exercises/math/scratch/index.js +14 -0
- package/lib/exercises/math/scratch/scratchCond1.d.ts +25 -0
- package/lib/exercises/math/scratch/scratchCond1.d.ts.map +1 -0
- package/lib/exercises/math/scratch/scratchCond1.js +290 -0
- package/lib/exercises/math/scratch/scratchFunction1.d.ts +9 -0
- package/lib/exercises/math/scratch/scratchFunction1.d.ts.map +1 -0
- package/lib/exercises/math/scratch/scratchFunction1.js +199 -0
- package/lib/exercises/math/scratch/scratchLoop1.d.ts +10 -0
- package/lib/exercises/math/scratch/scratchLoop1.d.ts.map +1 -0
- package/lib/exercises/math/scratch/scratchLoop1.js +207 -0
- package/lib/exercises/math/scratch/scratchLoopCond1.d.ts +12 -0
- package/lib/exercises/math/scratch/scratchLoopCond1.d.ts.map +1 -0
- package/lib/exercises/math/scratch/scratchLoopCond1.js +236 -0
- package/lib/exercises/math/scratch/scratchLoopCond2.d.ts +14 -0
- package/lib/exercises/math/scratch/scratchLoopCond2.d.ts.map +1 -0
- package/lib/exercises/math/scratch/scratchLoopCond2.js +219 -0
- package/lib/exercises/math/scratch/scratchOperations1.d.ts +8 -0
- package/lib/exercises/math/scratch/scratchOperations1.d.ts.map +1 -0
- package/lib/exercises/math/scratch/scratchOperations1.js +245 -0
- package/lib/exercises/math/scratch/scratchOperations2.d.ts +10 -0
- package/lib/exercises/math/scratch/scratchOperations2.d.ts.map +1 -0
- package/lib/exercises/math/scratch/scratchOperations2.js +324 -0
- package/lib/exercises/math/scratch/scratchPrintXY.d.ts +9 -0
- package/lib/exercises/math/scratch/scratchPrintXY.d.ts.map +1 -0
- package/lib/exercises/math/scratch/scratchPrintXY.js +194 -0
- package/lib/exercises/math/scratch/scratchStringLoop.d.ts +10 -0
- package/lib/exercises/math/scratch/scratchStringLoop.d.ts.map +1 -0
- package/lib/exercises/math/scratch/scratchStringLoop.js +192 -0
- package/lib/exercises/math/scratch/scratchStringLoopCond.d.ts +12 -0
- package/lib/exercises/math/scratch/scratchStringLoopCond.d.ts.map +1 -0
- package/lib/exercises/math/scratch/scratchStringLoopCond.js +270 -0
- package/lib/exercises/math/scratch/scratchStringLoopCond2.d.ts +12 -0
- package/lib/exercises/math/scratch/scratchStringLoopCond2.d.ts.map +1 -0
- package/lib/exercises/math/scratch/scratchStringLoopCond2.js +273 -0
- package/lib/exercises/math/scratch/scratchStringLoopCond3.d.ts +12 -0
- package/lib/exercises/math/scratch/scratchStringLoopCond3.d.ts.map +1 -0
- package/lib/exercises/math/scratch/scratchStringLoopCond3.js +275 -0
- package/lib/exercises/math/scratch/scratchSwapUsingTmp.d.ts +10 -0
- package/lib/exercises/math/scratch/scratchSwapUsingTmp.d.ts.map +1 -0
- package/lib/exercises/math/scratch/scratchSwapUsingTmp.js +199 -0
- package/lib/exercises/math/scratch/scratchVarWaterfall.d.ts +10 -0
- package/lib/exercises/math/scratch/scratchVarWaterfall.d.ts.map +1 -0
- package/lib/exercises/math/scratch/scratchVarWaterfall.js +371 -0
- package/lib/index.d.ts +86 -1
- package/lib/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { addValidProp, tryToAddWrongProp, } from "../../../exercises/exercise.js";
|
|
2
|
+
import { getDistinctQuestions } from "../../../exercises/utils/getDistinctQuestions.js";
|
|
3
|
+
import { randint } from "../../../math/utils/random/randint.js";
|
|
4
|
+
import { shuffle } from "../../../utils/alea/shuffle.js";
|
|
5
|
+
const getInstruction = (identifiers) => {
|
|
6
|
+
const { xStart, yStart, rand } = identifiers;
|
|
7
|
+
return `On considère le programme Scratch ci-dessous :
|
|
8
|
+
|
|
9
|
+
<svg id="scratch">
|
|
10
|
+
quand @greenFlag est cliqué
|
|
11
|
+
mettre [x v] à [${xStart}]
|
|
12
|
+
mettre [y v] à [${yStart}]
|
|
13
|
+
${(() => {
|
|
14
|
+
switch (rand) {
|
|
15
|
+
//"x+y"
|
|
16
|
+
case 0:
|
|
17
|
+
return `dire [x + y]`;
|
|
18
|
+
case 1:
|
|
19
|
+
return `dire (regrouper [x] et (regrouper [+] et [y]))`;
|
|
20
|
+
//`${x}+${y}`
|
|
21
|
+
case 2:
|
|
22
|
+
return `dire (regrouper (x) et (regrouper [+] et (y)))`;
|
|
23
|
+
//`${x+y}`
|
|
24
|
+
case 3:
|
|
25
|
+
return `dire ((x) + (y))`;
|
|
26
|
+
//`x+${y}`
|
|
27
|
+
case 4:
|
|
28
|
+
return `dire (regrouper [x] et (regrouper [+] et (y)))`;
|
|
29
|
+
//`${x}+y`
|
|
30
|
+
case 5:
|
|
31
|
+
return `dire (regrouper (x) et (regrouper [+] et [y]))`;
|
|
32
|
+
}
|
|
33
|
+
})()}
|
|
34
|
+
</svg>
|
|
35
|
+
|
|
36
|
+
Que va dire le lutin quand on va exécuter le programme ?`;
|
|
37
|
+
};
|
|
38
|
+
const getFunctionForScratchProgram = (identifiers) => {
|
|
39
|
+
const { xStart, yStart, rand } = identifiers;
|
|
40
|
+
return (_) => {
|
|
41
|
+
const outDict = {};
|
|
42
|
+
//init
|
|
43
|
+
const x = xStart;
|
|
44
|
+
const y = yStart;
|
|
45
|
+
//convenience: store last step in -1
|
|
46
|
+
outDict[-1] = (() => {
|
|
47
|
+
switch (rand) {
|
|
48
|
+
case 0:
|
|
49
|
+
case 1:
|
|
50
|
+
return "x+y";
|
|
51
|
+
case 2:
|
|
52
|
+
return `${x}+${y}`;
|
|
53
|
+
case 3:
|
|
54
|
+
return `${x + y}`;
|
|
55
|
+
case 4:
|
|
56
|
+
return `x+${y}`;
|
|
57
|
+
case 5:
|
|
58
|
+
return `${x}+y`;
|
|
59
|
+
default:
|
|
60
|
+
throw new Error("unsupported rand: " + rand);
|
|
61
|
+
}
|
|
62
|
+
})();
|
|
63
|
+
return outDict;
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
const getAnswer = (identifiers) => {
|
|
67
|
+
const dictSteps = getFunctionForScratchProgram(identifiers)(identifiers);
|
|
68
|
+
return dictSteps[-1];
|
|
69
|
+
};
|
|
70
|
+
const getHint = () => {
|
|
71
|
+
return `Pour chaque variable, est-ce qu'on te demande d'afficher son nom, ou bien sa valeur ?`;
|
|
72
|
+
};
|
|
73
|
+
const getCorrection = (identifiers) => {
|
|
74
|
+
const { xStart, yStart, rand } = identifiers;
|
|
75
|
+
return `Initialement, $x$ vaut $${xStart}$ et $y$ vaut $${yStart}$.
|
|
76
|
+
|
|
77
|
+
${(() => {
|
|
78
|
+
switch (rand) {
|
|
79
|
+
case 0:
|
|
80
|
+
return `Dans l'instruction dire ..., ce qui est en blanc, c'est la chaîne de caractères "x+y".
|
|
81
|
+
|
|
82
|
+
Le lutin va donc dire: "x+y" (Tout simplement !).`;
|
|
83
|
+
case 1:
|
|
84
|
+
return `Dans l'instruction dire ..., ce qui est en blanc, ce sont les chaînes de caractères "x", "+" et "y".
|
|
85
|
+
|
|
86
|
+
On les regroupe.
|
|
87
|
+
|
|
88
|
+
Le lutin va donc dire: "x+y".`;
|
|
89
|
+
case 2:
|
|
90
|
+
return `Dans l'instruction dire ..., ce qui est en blanc, c'est uniquement la chaîne de caractères "+".
|
|
91
|
+
|
|
92
|
+
On va donc construire des chaînes de caractères avec les valeurs des variables $x$ et $y$.
|
|
93
|
+
|
|
94
|
+
Ensuite, on regroupe tout.
|
|
95
|
+
|
|
96
|
+
Le lutin va donc dire : "$${xStart}$+$${yStart}$".`;
|
|
97
|
+
case 3:
|
|
98
|
+
return `Dans l'instruction dire ..., il n'y a rien en blanc.
|
|
99
|
+
|
|
100
|
+
On va donc calculer la somme $${xStart}$ + $${yStart}$ et la transformer en chaîne de caractères.
|
|
101
|
+
|
|
102
|
+
Le lutin va donc dire : "$${xStart + yStart}$".`;
|
|
103
|
+
case 4:
|
|
104
|
+
return `Dans l'instruction dire ..., ce qui est en blanc, ce sont les chaînes de caractères "x" et "+".
|
|
105
|
+
|
|
106
|
+
On va donc construire une chaîne de caractères avec la valeur de la variable $y$.
|
|
107
|
+
|
|
108
|
+
Ensuite, on regroupe tout.
|
|
109
|
+
|
|
110
|
+
Le lutin va donc dire : "x+$${yStart}$".`;
|
|
111
|
+
case 5:
|
|
112
|
+
return `Dans l'instruction dire ..., ce qui est en blanc, ce sont les chaînes de caractères "+" et "y".
|
|
113
|
+
|
|
114
|
+
On va donc construire une chaîne de caractères avec la valeur de la variable $x$.
|
|
115
|
+
|
|
116
|
+
Ensuite, on regroupe tout.
|
|
117
|
+
|
|
118
|
+
Le lutin va donc dire : "$${xStart}$+y".`;
|
|
119
|
+
default:
|
|
120
|
+
throw new Error("unsupported rand: " + rand);
|
|
121
|
+
}
|
|
122
|
+
})()}
|
|
123
|
+
|
|
124
|
+
`;
|
|
125
|
+
};
|
|
126
|
+
const getPropositions = (n, { answer, ...identifiers }) => {
|
|
127
|
+
const propositions = [];
|
|
128
|
+
addValidProp(propositions, answer);
|
|
129
|
+
//mandatory
|
|
130
|
+
[3].forEach((rand) => {
|
|
131
|
+
const identifiersWrong = Object.assign({}, identifiers, {
|
|
132
|
+
rand,
|
|
133
|
+
});
|
|
134
|
+
const texWrong = getAnswer(identifiersWrong);
|
|
135
|
+
tryToAddWrongProp(propositions, texWrong);
|
|
136
|
+
});
|
|
137
|
+
//filler
|
|
138
|
+
[...Array(6).keys()].forEach((rand) => {
|
|
139
|
+
if (propositions.length < n) {
|
|
140
|
+
const identifiersWrong = Object.assign({}, identifiers, {
|
|
141
|
+
rand,
|
|
142
|
+
});
|
|
143
|
+
const texWrong = getAnswer(identifiersWrong);
|
|
144
|
+
tryToAddWrongProp(propositions, texWrong);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
return shuffle(propositions);
|
|
148
|
+
};
|
|
149
|
+
const getKeys = () => {
|
|
150
|
+
return ["x", "y"];
|
|
151
|
+
};
|
|
152
|
+
const isAnswerValid = (ans, { answer }) => {
|
|
153
|
+
return ans === answer;
|
|
154
|
+
};
|
|
155
|
+
const getScratchPrintXYQuestion = () => {
|
|
156
|
+
const xStart = randint(-10, 10);
|
|
157
|
+
const yStart = randint(-10, 10);
|
|
158
|
+
const rand = randint(0, 6);
|
|
159
|
+
const identifiers = {
|
|
160
|
+
xStart,
|
|
161
|
+
yStart,
|
|
162
|
+
rand,
|
|
163
|
+
};
|
|
164
|
+
return getQuestionFromIdentifiers(identifiers);
|
|
165
|
+
};
|
|
166
|
+
const getQuestionFromIdentifiers = (identifiers) => {
|
|
167
|
+
return {
|
|
168
|
+
answer: getAnswer(identifiers),
|
|
169
|
+
instruction: getInstruction(identifiers),
|
|
170
|
+
keys: getKeys(identifiers),
|
|
171
|
+
answerFormat: "tex",
|
|
172
|
+
identifiers,
|
|
173
|
+
hint: getHint(identifiers),
|
|
174
|
+
correction: getCorrection(identifiers),
|
|
175
|
+
};
|
|
176
|
+
};
|
|
177
|
+
export const scratchPrintXY = {
|
|
178
|
+
id: "scratchPrintXY",
|
|
179
|
+
connector: "=",
|
|
180
|
+
label: "Afficher des chaînes de caractères et/ou des valeurs de variables en Scratch",
|
|
181
|
+
isSingleStep: true,
|
|
182
|
+
generator: (nb, opts) => getDistinctQuestions(() => getScratchPrintXYQuestion(opts), nb),
|
|
183
|
+
qcmTimer: 60,
|
|
184
|
+
freeTimer: 60,
|
|
185
|
+
getPropositions,
|
|
186
|
+
isAnswerValid,
|
|
187
|
+
subject: "Mathématiques",
|
|
188
|
+
getInstruction,
|
|
189
|
+
getHint,
|
|
190
|
+
getCorrection,
|
|
191
|
+
getAnswer,
|
|
192
|
+
getQuestionFromIdentifiers,
|
|
193
|
+
hasHintAndCorrection: true,
|
|
194
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Exercise } from "../../../exercises/exercise.js";
|
|
2
|
+
type Identifiers = {
|
|
3
|
+
strStart: string;
|
|
4
|
+
repeatCount: number;
|
|
5
|
+
strAppend1: string;
|
|
6
|
+
rand: number;
|
|
7
|
+
};
|
|
8
|
+
export declare const scratchStringLoop: Exercise<Identifiers>;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=scratchStringLoop.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scratchStringLoop.d.ts","sourceRoot":"","sources":["../../../../src/exercises/math/scratch/scratchStringLoop.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAcT,MAAM,6BAA6B,CAAC;AAMrC,KAAK,WAAW,GAAG;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AA8MF,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,WAAW,CAkBnD,CAAC"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { addValidProp, shuffleProps, tryToAddWrongProp, } from "../../../exercises/exercise.js";
|
|
2
|
+
import { getDistinctQuestions } from "../../../exercises/utils/getDistinctQuestions.js";
|
|
3
|
+
import { randint } from "../../../math/utils/random/randint.js";
|
|
4
|
+
import { coinFlip } from "../../../utils/alea/coinFlip.js";
|
|
5
|
+
import { random } from "../../../utils/alea/random.js";
|
|
6
|
+
const getInstruction = (identifiers) => {
|
|
7
|
+
const { strStart, repeatCount, strAppend1, rand } = identifiers;
|
|
8
|
+
return `On considère le programme Scratch ci-dessous :
|
|
9
|
+
|
|
10
|
+
<svg id="scratch">
|
|
11
|
+
quand @greenFlag est cliqué
|
|
12
|
+
mettre [x v] à [${strStart}]
|
|
13
|
+
répéter (${repeatCount}) fois
|
|
14
|
+
${(() => {
|
|
15
|
+
switch (rand) {
|
|
16
|
+
case 0:
|
|
17
|
+
return ` mettre [x v] à (regrouper (x) et [${strAppend1}])`;
|
|
18
|
+
case 1:
|
|
19
|
+
return ` mettre [x v] à (regrouper [${strAppend1}] et (x))`;
|
|
20
|
+
case 2:
|
|
21
|
+
return ` mettre [x v] à (regrouper (x) et (x))`;
|
|
22
|
+
case 3:
|
|
23
|
+
return ` mettre [x v] à (regrouper [${strAppend1}] et [${strAppend1}])`;
|
|
24
|
+
}
|
|
25
|
+
})()}
|
|
26
|
+
</svg>
|
|
27
|
+
|
|
28
|
+
Quelle est la valeur de $x$ à la fin de l'exécution du programme ?`;
|
|
29
|
+
};
|
|
30
|
+
const getFunctionForScratchProgram = (identifiers) => {
|
|
31
|
+
const { strStart, repeatCount, strAppend1, rand } = identifiers;
|
|
32
|
+
return (_) => {
|
|
33
|
+
const outDict = {};
|
|
34
|
+
//init
|
|
35
|
+
let x;
|
|
36
|
+
x = strStart;
|
|
37
|
+
outDict[0] = {
|
|
38
|
+
x,
|
|
39
|
+
};
|
|
40
|
+
//loop
|
|
41
|
+
let counter = 0;
|
|
42
|
+
while (counter < repeatCount) {
|
|
43
|
+
counter++;
|
|
44
|
+
//inside of loop
|
|
45
|
+
{
|
|
46
|
+
x = (() => {
|
|
47
|
+
switch (rand) {
|
|
48
|
+
case 0:
|
|
49
|
+
return x + strAppend1;
|
|
50
|
+
case 1:
|
|
51
|
+
return strAppend1 + x;
|
|
52
|
+
case 2:
|
|
53
|
+
return x + x;
|
|
54
|
+
case 3:
|
|
55
|
+
return strAppend1 + strAppend1;
|
|
56
|
+
default:
|
|
57
|
+
throw new Error("unsupported rand: " + rand);
|
|
58
|
+
}
|
|
59
|
+
})();
|
|
60
|
+
}
|
|
61
|
+
//store step dict
|
|
62
|
+
outDict[counter] = {
|
|
63
|
+
x,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//convenience: store last step in -1
|
|
67
|
+
outDict[-1] = outDict[Math.max(...Object.keys(outDict).map((k) => +k))];
|
|
68
|
+
return outDict;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
const getAnswer = (identifiers) => {
|
|
72
|
+
return getFunctionForScratchProgram(identifiers)(identifiers)[-1].x;
|
|
73
|
+
};
|
|
74
|
+
const getHint = () => {
|
|
75
|
+
return `La valeur de la variable $x$ change au cours de l'exécution du programme.
|
|
76
|
+
À chaque itération,
|
|
77
|
+
détermine comment la variable évolue.`;
|
|
78
|
+
};
|
|
79
|
+
const getCorrection = (identifiers) => {
|
|
80
|
+
const { strAppend1, rand } = identifiers;
|
|
81
|
+
const dictSteps = getFunctionForScratchProgram(identifiers)(identifiers);
|
|
82
|
+
return `Initialement, $x$ vaut $${dictSteps[0].x}$.
|
|
83
|
+
|
|
84
|
+
${Object.keys(dictSteps)
|
|
85
|
+
.map((k) => +k)
|
|
86
|
+
.filter((k) => k > 0)
|
|
87
|
+
.map((k) => {
|
|
88
|
+
return `Itération n°$${k}$ :
|
|
89
|
+
|
|
90
|
+
Au début, $x$ vaut $${dictSteps[k - 1].x}$.
|
|
91
|
+
|
|
92
|
+
On va affecter à $x$ la chaîne de caractères composée par le regroupement de ${(() => {
|
|
93
|
+
switch (rand) {
|
|
94
|
+
case 0:
|
|
95
|
+
return `$${dictSteps[k - 1].x}$ et de $${strAppend1}$`;
|
|
96
|
+
case 1:
|
|
97
|
+
return `$${strAppend1}$ et de $${dictSteps[k - 1].x}$`;
|
|
98
|
+
case 2:
|
|
99
|
+
return `$${dictSteps[k - 1].x}$ et de $${dictSteps[k - 1].x}$`;
|
|
100
|
+
case 3:
|
|
101
|
+
return `$${strAppend1}$ et de $${strAppend1}$`;
|
|
102
|
+
default:
|
|
103
|
+
throw new Error("unsupported rand: " + rand);
|
|
104
|
+
}
|
|
105
|
+
})()}.
|
|
106
|
+
|
|
107
|
+
$x$ vaut maintenant $${dictSteps[k].x}$.`;
|
|
108
|
+
}).join(`
|
|
109
|
+
|
|
110
|
+
`)}
|
|
111
|
+
|
|
112
|
+
À la fin de l'exécution du programme, $x$ vaut donc $${dictSteps[-1].x}$.`;
|
|
113
|
+
};
|
|
114
|
+
const getPropositions = (n, { answer, ...identifiers }) => {
|
|
115
|
+
const { strStart, repeatCount, rand } = identifiers;
|
|
116
|
+
const propositions = [];
|
|
117
|
+
addValidProp(propositions, answer);
|
|
118
|
+
[...Array(4).keys()].forEach((rand) => {
|
|
119
|
+
const identifiersWrong = Object.assign({}, identifiers, {
|
|
120
|
+
rand,
|
|
121
|
+
});
|
|
122
|
+
const texWrong = getAnswer(identifiersWrong);
|
|
123
|
+
tryToAddWrongProp(propositions, texWrong);
|
|
124
|
+
});
|
|
125
|
+
//strStart
|
|
126
|
+
tryToAddWrongProp(propositions, strStart);
|
|
127
|
+
//terror for rand===3
|
|
128
|
+
if (rand === 2) {
|
|
129
|
+
if (coinFlip()) {
|
|
130
|
+
const texWrong = strStart.repeat(2 ** repeatCount - 1);
|
|
131
|
+
tryToAddWrongProp(propositions, texWrong);
|
|
132
|
+
}
|
|
133
|
+
if (strStart.length === 1) {
|
|
134
|
+
if (coinFlip()) {
|
|
135
|
+
const texWrong = strStart.repeat(2 ** repeatCount + 1);
|
|
136
|
+
tryToAddWrongProp(propositions, texWrong);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return shuffleProps(propositions, n);
|
|
141
|
+
};
|
|
142
|
+
const getKeys = () => {
|
|
143
|
+
return ["A", "B", "C", "D"];
|
|
144
|
+
};
|
|
145
|
+
const isAnswerValid = (ans, { answer }) => {
|
|
146
|
+
return ans === answer;
|
|
147
|
+
};
|
|
148
|
+
const getScratchStringLoopQuestion = () => {
|
|
149
|
+
const rand = randint(0, 4);
|
|
150
|
+
function createRandomStr(length) {
|
|
151
|
+
return [...Array(length).keys()].reduce((acc, _) => acc + random(["A", "B", "C", "D"]), "");
|
|
152
|
+
}
|
|
153
|
+
const repeatCount = randint(1, 4);
|
|
154
|
+
const strStart = createRandomStr(rand === 2 && repeatCount === 3 ? 1 : randint(1, 3));
|
|
155
|
+
const strAppend1 = createRandomStr(randint(1, 3));
|
|
156
|
+
const identifiers = {
|
|
157
|
+
strStart,
|
|
158
|
+
repeatCount,
|
|
159
|
+
strAppend1,
|
|
160
|
+
rand,
|
|
161
|
+
};
|
|
162
|
+
return getQuestionFromIdentifiers(identifiers);
|
|
163
|
+
};
|
|
164
|
+
const getQuestionFromIdentifiers = (identifiers) => {
|
|
165
|
+
return {
|
|
166
|
+
answer: getAnswer(identifiers),
|
|
167
|
+
instruction: getInstruction(identifiers),
|
|
168
|
+
keys: getKeys(identifiers),
|
|
169
|
+
answerFormat: "tex",
|
|
170
|
+
identifiers,
|
|
171
|
+
hint: getHint(identifiers),
|
|
172
|
+
correction: getCorrection(identifiers),
|
|
173
|
+
};
|
|
174
|
+
};
|
|
175
|
+
export const scratchStringLoop = {
|
|
176
|
+
id: "scratchStringLoop",
|
|
177
|
+
connector: "=",
|
|
178
|
+
label: "Utiliser une boucle avec une chaîne de caractères en Scratch",
|
|
179
|
+
isSingleStep: true,
|
|
180
|
+
generator: (nb, opts) => getDistinctQuestions(() => getScratchStringLoopQuestion(opts), nb),
|
|
181
|
+
qcmTimer: 60,
|
|
182
|
+
freeTimer: 60,
|
|
183
|
+
getPropositions,
|
|
184
|
+
isAnswerValid,
|
|
185
|
+
subject: "Mathématiques",
|
|
186
|
+
getInstruction,
|
|
187
|
+
getHint,
|
|
188
|
+
getCorrection,
|
|
189
|
+
getAnswer,
|
|
190
|
+
getQuestionFromIdentifiers,
|
|
191
|
+
hasHintAndCorrection: true,
|
|
192
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Exercise } from "../../../exercises/exercise.js";
|
|
2
|
+
type Identifiers = {
|
|
3
|
+
strStart: string;
|
|
4
|
+
repeatCount: number;
|
|
5
|
+
isGreaterCond1: boolean;
|
|
6
|
+
thresholdCond1: number;
|
|
7
|
+
arrStrAppend: string[];
|
|
8
|
+
arrRand: number[];
|
|
9
|
+
};
|
|
10
|
+
export declare const scratchStringLoopCond: Exercise<Identifiers>;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=scratchStringLoopCond.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scratchStringLoopCond.d.ts","sourceRoot":"","sources":["../../../../src/exercises/math/scratch/scratchStringLoopCond.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAcT,MAAM,6BAA6B,CAAC;AAqBrC,KAAK,WAAW,GAAG;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,OAAO,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AA4SF,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,WAAW,CAmBvD,CAAC"}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { addValidProp, shuffleProps, tryToAddWrongProp, } from "../../../exercises/exercise.js";
|
|
2
|
+
import { getDistinctQuestions } from "../../../exercises/utils/getDistinctQuestions.js";
|
|
3
|
+
import { randint } from "../../../math/utils/random/randint.js";
|
|
4
|
+
import { coinFlip } from "../../../utils/alea/coinFlip.js";
|
|
5
|
+
import { probaFlip } from "../../../utils/alea/probaFlip.js";
|
|
6
|
+
import { random, randomMany } from "../../../utils/alea/random.js";
|
|
7
|
+
import { getCartesiansProducts } from "../../../utils/arrays/cartesianProducts.js";
|
|
8
|
+
const getStrScratchForRand = (rand, strAppend) => {
|
|
9
|
+
switch (rand) {
|
|
10
|
+
case 0:
|
|
11
|
+
return ` mettre [x v] à (regrouper (x) et [${strAppend}])`;
|
|
12
|
+
case 1:
|
|
13
|
+
return ` mettre [x v] à (regrouper [${strAppend}] et (x))`;
|
|
14
|
+
case 2:
|
|
15
|
+
return ` mettre [x v] à (regrouper (x) et (x))`;
|
|
16
|
+
case 3:
|
|
17
|
+
return ` mettre [x v] à (regrouper [${strAppend}] et [${strAppend}])`;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
const getInstruction = (identifiers) => {
|
|
21
|
+
const { strStart, repeatCount, isGreaterCond1, thresholdCond1, arrStrAppend, arrRand, } = identifiers;
|
|
22
|
+
return `On considère le programme Scratch ci-dessous :
|
|
23
|
+
|
|
24
|
+
<svg id="scratch">
|
|
25
|
+
quand @greenFlag est cliqué
|
|
26
|
+
mettre [x v] à [${strStart}]
|
|
27
|
+
répéter (${repeatCount}) fois
|
|
28
|
+
si <(longueur de (x)) ${isGreaterCond1 ? ">" : "\\<"} (${thresholdCond1})> alors
|
|
29
|
+
${arrRand.map((rand, i) => `${getStrScratchForRand(rand, arrStrAppend[i])}
|
|
30
|
+
`).join(`sinon
|
|
31
|
+
`)}
|
|
32
|
+
</svg>
|
|
33
|
+
|
|
34
|
+
Quelle est la valeur de $x$ à la fin de l'exécution du programme ?`;
|
|
35
|
+
};
|
|
36
|
+
const getFunctionForScratchProgram = (identifiers) => {
|
|
37
|
+
const { strStart, repeatCount, isGreaterCond1, thresholdCond1, arrStrAppend, arrRand, } = identifiers;
|
|
38
|
+
return (_) => {
|
|
39
|
+
const outDict = {};
|
|
40
|
+
//init
|
|
41
|
+
let x;
|
|
42
|
+
x = strStart;
|
|
43
|
+
outDict[0] = {
|
|
44
|
+
x,
|
|
45
|
+
};
|
|
46
|
+
function strForXAndRandAndStrAppend(x, rand, strAppend) {
|
|
47
|
+
switch (rand) {
|
|
48
|
+
case 0:
|
|
49
|
+
return x + strAppend;
|
|
50
|
+
case 1:
|
|
51
|
+
return strAppend + x;
|
|
52
|
+
case 2:
|
|
53
|
+
return x + x;
|
|
54
|
+
case 3:
|
|
55
|
+
return strAppend + strAppend;
|
|
56
|
+
default:
|
|
57
|
+
throw new Error("unsupported rand: " + rand);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//loop
|
|
61
|
+
let counter = 0;
|
|
62
|
+
while (counter < repeatCount) {
|
|
63
|
+
counter++;
|
|
64
|
+
//inside of loop
|
|
65
|
+
{
|
|
66
|
+
if (isGreaterCond1 ? x.length > thresholdCond1 : x.length < thresholdCond1) {
|
|
67
|
+
x = strForXAndRandAndStrAppend(x, arrRand[0], arrStrAppend[0]);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
x = strForXAndRandAndStrAppend(x, arrRand[1], arrStrAppend[1]);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//store step dict
|
|
74
|
+
outDict[counter] = {
|
|
75
|
+
x,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
//convenience: store last step in -1
|
|
79
|
+
outDict[-1] = outDict[Math.max(...Object.keys(outDict).map((k) => +k))];
|
|
80
|
+
return outDict;
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
const getAnswer = (identifiers) => {
|
|
84
|
+
return getFunctionForScratchProgram(identifiers)(identifiers)[-1].x;
|
|
85
|
+
};
|
|
86
|
+
const getHint = () => {
|
|
87
|
+
return `La valeur de la variable $x$ change au cours de l'exécution du programme.
|
|
88
|
+
À chaque itération,
|
|
89
|
+
détermine comment la variable évolue.
|
|
90
|
+
La longueur d'une chaîne de caractères est le nombre de caractères qu'elle contient (exemple : "AAC" est de longueur $3$).`;
|
|
91
|
+
};
|
|
92
|
+
const getCorrection = (identifiers) => {
|
|
93
|
+
const { isGreaterCond1, thresholdCond1, arrRand, arrStrAppend } = identifiers;
|
|
94
|
+
const dictSteps = getFunctionForScratchProgram(identifiers)(identifiers);
|
|
95
|
+
return `Initialement, $x$ vaut $${dictSteps[0].x}$.
|
|
96
|
+
|
|
97
|
+
${Object.keys(dictSteps)
|
|
98
|
+
.map((k) => +k)
|
|
99
|
+
.filter((k) => k > 0)
|
|
100
|
+
.map((k) => {
|
|
101
|
+
const x = dictSteps[k - 1].x;
|
|
102
|
+
const isConditionVerified = isGreaterCond1
|
|
103
|
+
? x.length > thresholdCond1
|
|
104
|
+
: x.length < thresholdCond1;
|
|
105
|
+
const indexCondition = isConditionVerified ? 0 : 1;
|
|
106
|
+
const rand = arrRand[indexCondition];
|
|
107
|
+
const strAppend1 = arrStrAppend[indexCondition];
|
|
108
|
+
return `Itération n°$${k}$ :
|
|
109
|
+
|
|
110
|
+
Au début, $x$ vaut $${x}$.
|
|
111
|
+
|
|
112
|
+
La longueur de $x$ est $${x.length}$.
|
|
113
|
+
|
|
114
|
+
La condition ${isConditionVerified ? "est vérifiée" : "n'est pas vérifiée"}.
|
|
115
|
+
|
|
116
|
+
On va affecter à $x$ la chaîne de caractères composée par le regroupement de ${(() => {
|
|
117
|
+
switch (rand) {
|
|
118
|
+
case 0:
|
|
119
|
+
return `$${dictSteps[k - 1].x}$ et de $${strAppend1}$`;
|
|
120
|
+
case 1:
|
|
121
|
+
return `$${strAppend1}$ et de $${dictSteps[k - 1].x}$`;
|
|
122
|
+
case 2:
|
|
123
|
+
return `$${dictSteps[k - 1].x}$ et de $${dictSteps[k - 1].x}$`;
|
|
124
|
+
case 3:
|
|
125
|
+
return `$${strAppend1}$ et de $${strAppend1}$`;
|
|
126
|
+
default:
|
|
127
|
+
throw new Error("unsupported rand: " + rand);
|
|
128
|
+
}
|
|
129
|
+
})()}.
|
|
130
|
+
|
|
131
|
+
$x$ vaut maintenant $${dictSteps[k].x}$.`;
|
|
132
|
+
}).join(`
|
|
133
|
+
|
|
134
|
+
`)}
|
|
135
|
+
|
|
136
|
+
À la fin de l'exécution du programme, $x$ vaut donc $${dictSteps[-1].x}$.`;
|
|
137
|
+
};
|
|
138
|
+
const getPropositions = (n, { answer, ...identifiers }) => {
|
|
139
|
+
const { strStart, repeatCount, arrRand, arrStrAppend } = identifiers;
|
|
140
|
+
const propositions = [];
|
|
141
|
+
addValidProp(propositions, answer);
|
|
142
|
+
//toggle on all checks
|
|
143
|
+
{
|
|
144
|
+
const identifiersWrong = Object.assign({}, identifiers, {
|
|
145
|
+
arrRand: arrRand.toReversed(),
|
|
146
|
+
arrStrAppend: arrStrAppend.toReversed(),
|
|
147
|
+
});
|
|
148
|
+
const texWrong = getAnswer(identifiersWrong);
|
|
149
|
+
tryToAddWrongProp(propositions, texWrong);
|
|
150
|
+
}
|
|
151
|
+
//ABB instead of BBA
|
|
152
|
+
if (arrRand.includes(0) || arrRand.includes(1)) {
|
|
153
|
+
const identifiersWrong = Object.assign({}, identifiers, {
|
|
154
|
+
arrRand: arrRand.map((rand) => (rand === 0 ? 1 : rand === 1 ? 0 : rand)),
|
|
155
|
+
arrStrAppend: arrStrAppend.toReversed(),
|
|
156
|
+
});
|
|
157
|
+
const texWrong = getAnswer(identifiersWrong);
|
|
158
|
+
tryToAddWrongProp(propositions, texWrong);
|
|
159
|
+
}
|
|
160
|
+
//wrong repeatCount
|
|
161
|
+
{
|
|
162
|
+
const identifiersWrong = Object.assign({}, identifiers, {
|
|
163
|
+
repeatCount: repeatCount - 1,
|
|
164
|
+
});
|
|
165
|
+
const texWrong = getAnswer(identifiersWrong);
|
|
166
|
+
tryToAddWrongProp(propositions, texWrong);
|
|
167
|
+
}
|
|
168
|
+
//strStart
|
|
169
|
+
tryToAddWrongProp(propositions, strStart);
|
|
170
|
+
//filler
|
|
171
|
+
[...Array(repeatCount + 4).keys()].forEach((repeatCountW) => {
|
|
172
|
+
let strWrong = strStart;
|
|
173
|
+
[...Array(repeatCountW).keys()].forEach(() => {
|
|
174
|
+
const strAppend = random(arrStrAppend);
|
|
175
|
+
if (coinFlip()) {
|
|
176
|
+
strWrong = strWrong + strAppend;
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
strWrong = strAppend + strWrong;
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
if (propositions.length < n) {
|
|
183
|
+
tryToAddWrongProp(propositions, strWrong);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
["A", "B", "C", "D"].forEach((strWrong) => {
|
|
187
|
+
if (propositions.length < n) {
|
|
188
|
+
tryToAddWrongProp(propositions, strWrong);
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
return shuffleProps(propositions, n);
|
|
192
|
+
};
|
|
193
|
+
const getKeys = () => {
|
|
194
|
+
return ["A", "B", "C", "D"];
|
|
195
|
+
};
|
|
196
|
+
const isAnswerValid = (ans, { answer }) => {
|
|
197
|
+
return ans === answer;
|
|
198
|
+
};
|
|
199
|
+
const getScratchStringLoopCondQuestion = () => {
|
|
200
|
+
const arrRand = randomMany([0, 1, 2, 3], 2);
|
|
201
|
+
function createRandomStr(length) {
|
|
202
|
+
return [...Array(length).keys()].reduce((acc, _) => acc + random(["A", "B", "C", "D"]), "");
|
|
203
|
+
}
|
|
204
|
+
function createAllPossibleStrings(minLength, maxLength) {
|
|
205
|
+
return [...Array(maxLength - minLength).keys()]
|
|
206
|
+
.map((i) => i + minLength)
|
|
207
|
+
.reduce((acc, length) => {
|
|
208
|
+
const arrSrc = [...Array(length).keys()].map(() => [
|
|
209
|
+
"A",
|
|
210
|
+
"B",
|
|
211
|
+
"C",
|
|
212
|
+
"D",
|
|
213
|
+
]);
|
|
214
|
+
const arrCartesianProduct = getCartesiansProducts(arrSrc);
|
|
215
|
+
const arrStr = arrCartesianProduct.map((arr) => arr.join(""));
|
|
216
|
+
acc.push(...arrStr);
|
|
217
|
+
return acc;
|
|
218
|
+
}, []);
|
|
219
|
+
}
|
|
220
|
+
const repeatCount = arrRand.includes(2) ? randint(2, 4) : randint(2, 5);
|
|
221
|
+
const strStart = createRandomStr(arrRand.includes(2) && repeatCount === 3 ? 1 : randint(1, 3));
|
|
222
|
+
let arrStrAppend;
|
|
223
|
+
if (probaFlip(0.41)) {
|
|
224
|
+
const strAppendSame = random(createAllPossibleStrings(1, 3).filter((str) => str !== strStart));
|
|
225
|
+
arrStrAppend = [0, 1].map(() => strAppendSame);
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
arrStrAppend = [0, 1].map(() => createRandomStr(randint(1, 3)));
|
|
229
|
+
}
|
|
230
|
+
const isGreaterCond1 = coinFlip();
|
|
231
|
+
const thresholdCond1 = randint(3, 6);
|
|
232
|
+
const identifiers = {
|
|
233
|
+
strStart,
|
|
234
|
+
repeatCount,
|
|
235
|
+
arrStrAppend,
|
|
236
|
+
arrRand,
|
|
237
|
+
isGreaterCond1,
|
|
238
|
+
thresholdCond1,
|
|
239
|
+
};
|
|
240
|
+
return getQuestionFromIdentifiers(identifiers);
|
|
241
|
+
};
|
|
242
|
+
const getQuestionFromIdentifiers = (identifiers) => {
|
|
243
|
+
return {
|
|
244
|
+
answer: getAnswer(identifiers),
|
|
245
|
+
instruction: getInstruction(identifiers),
|
|
246
|
+
keys: getKeys(identifiers),
|
|
247
|
+
answerFormat: "tex",
|
|
248
|
+
identifiers,
|
|
249
|
+
hint: getHint(identifiers),
|
|
250
|
+
correction: getCorrection(identifiers),
|
|
251
|
+
};
|
|
252
|
+
};
|
|
253
|
+
export const scratchStringLoopCond = {
|
|
254
|
+
id: "scratchStringLoopCond",
|
|
255
|
+
connector: "=",
|
|
256
|
+
label: "Utiliser une condition dans une boucle avec une chaîne de caractères en Scratch",
|
|
257
|
+
isSingleStep: true,
|
|
258
|
+
generator: (nb, opts) => getDistinctQuestions(() => getScratchStringLoopCondQuestion(opts), nb),
|
|
259
|
+
qcmTimer: 60,
|
|
260
|
+
freeTimer: 60,
|
|
261
|
+
getPropositions,
|
|
262
|
+
isAnswerValid,
|
|
263
|
+
subject: "Mathématiques",
|
|
264
|
+
getInstruction,
|
|
265
|
+
getHint,
|
|
266
|
+
getCorrection,
|
|
267
|
+
getAnswer,
|
|
268
|
+
getQuestionFromIdentifiers,
|
|
269
|
+
hasHintAndCorrection: true,
|
|
270
|
+
};
|