math-exercises 3.0.216 → 3.0.217
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/calculLitteral/equation/exp/expOfFEqualsExpOfGEquation.d.ts.map +1 -1
- package/lib/exercises/math/calculLitteral/equation/exp/expOfFEqualsExpOfGEquation.js +19 -32
- package/lib/exercises/math/derivation/derivative/trigo/sinCosDerivativeRewriteUsingCos2PlusSin2Equals1.js +2 -2
- package/lib/exercises/math/graphs/graphsCheckIsConnectedGraph.d.ts +11 -0
- package/lib/exercises/math/graphs/graphsCheckIsConnectedGraph.d.ts.map +1 -0
- package/lib/exercises/math/graphs/graphsCheckIsConnectedGraph.js +178 -0
- package/lib/exercises/math/graphs/graphsCheckIsConnectedUndirectedGraph.js +1 -1
- package/lib/exercises/math/graphs/index.d.ts +1 -1
- package/lib/exercises/math/graphs/index.d.ts.map +1 -1
- package/lib/exercises/math/graphs/index.js +1 -1
- package/lib/exercises/math/integration/fromExpr/integralFromExpr.d.ts.map +1 -1
- package/lib/exercises/math/integration/fromExpr/integralFromExpr.js +2 -0
- package/lib/exercises/math/spaceGeometry/parametricLine/lineLineRelativePositionsFromParametricLines.d.ts.map +1 -1
- package/lib/exercises/math/spaceGeometry/parametricLine/lineLineRelativePositionsFromParametricLines.js +56 -3
- package/lib/exercises/math/spaceGeometry/planes/findNormalVectorFromPlaneEquation.d.ts.map +1 -1
- package/lib/exercises/math/spaceGeometry/planes/findNormalVectorFromPlaneEquation.js +6 -0
- package/lib/exercises/vea/treeTableVEA.d.ts.map +1 -1
- package/lib/exercises/vea/treeTableVEA.js +2 -0
- package/lib/math/graphs/graph.d.ts +1 -1
- package/lib/math/graphs/graph.d.ts.map +1 -1
- package/lib/math/graphs/graph.js +86 -30
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expOfFEqualsExpOfGEquation.d.ts","sourceRoot":"","sources":["../../../../../../src/exercises/math/calculLitteral/equation/exp/expOfFEqualsExpOfGEquation.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAoBT,MAAM,6BAA6B,CAAC;AA4DrC;;GAEG;AACH,KAAK,WAAW,GAAG;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;
|
|
1
|
+
{"version":3,"file":"expOfFEqualsExpOfGEquation.d.ts","sourceRoot":"","sources":["../../../../../../src/exercises/math/calculLitteral/equation/exp/expOfFEqualsExpOfGEquation.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAoBT,MAAM,6BAA6B,CAAC;AA4DrC;;GAEG;AACH,KAAK,WAAW,GAAG;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AA2ZF,KAAK,OAAO,GAAG;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAkCF,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,WAAW,EAAE,OAAO,CAoBrE,CAAC"}
|
|
@@ -268,6 +268,8 @@ const getKeys = (_, optsIn) => {
|
|
|
268
268
|
];
|
|
269
269
|
};
|
|
270
270
|
const isAnswerValid = (ans, { answer, ...identifiers }, optsIn) => {
|
|
271
|
+
console.log("ans", ans);
|
|
272
|
+
console.log("answer", answer);
|
|
271
273
|
const opts = optsIn ?? optsDefault;
|
|
272
274
|
const answerInputTypes = getAnswerInputTypes(opts);
|
|
273
275
|
const answerNode = getAnswerNode(identifiers);
|
|
@@ -276,27 +278,23 @@ const isAnswerValid = (ans, { answer, ...identifiers }, optsIn) => {
|
|
|
276
278
|
.elements;
|
|
277
279
|
function getParsedNodesForAnswerInputType(ans, answerInputType) {
|
|
278
280
|
switch (answerInputType) {
|
|
279
|
-
case "x=... ou x=...":
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
281
|
+
case "x=... ou x=...": {
|
|
282
|
+
const formated = ans
|
|
283
|
+
.replaceAll("text{ ou }", ";")
|
|
284
|
+
.replaceAll("x", "")
|
|
285
|
+
.replaceAll("=", "");
|
|
286
|
+
const elements = formated.split(";").map((e) => parseAlgebraic(e));
|
|
287
|
+
return elements;
|
|
288
|
+
}
|
|
289
|
+
case "S={...;...}": {
|
|
290
|
+
const discreteSetNodeCandidate = discreteSetParser(ans);
|
|
291
|
+
if (discreteSetNodeCandidate) {
|
|
292
|
+
return discreteSetNodeCandidate.elements;
|
|
287
293
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
{
|
|
291
|
-
const discreteSetNodeCandidate = discreteSetParser(ans);
|
|
292
|
-
if (discreteSetNodeCandidate) {
|
|
293
|
-
return discreteSetNodeCandidate.elements;
|
|
294
|
-
}
|
|
295
|
-
else {
|
|
296
|
-
return [];
|
|
297
|
-
}
|
|
294
|
+
else {
|
|
295
|
+
return [];
|
|
298
296
|
}
|
|
299
|
-
|
|
297
|
+
}
|
|
300
298
|
default:
|
|
301
299
|
throw new Error("Unsupported answerInputType: " + answerInputType);
|
|
302
300
|
}
|
|
@@ -325,19 +323,8 @@ const isAnswerValid = (ans, { answer, ...identifiers }, optsIn) => {
|
|
|
325
323
|
return answerInputTypes.some((answerInputType) => isAnswerValidForAnswerInputType(answerInputType));
|
|
326
324
|
}
|
|
327
325
|
else {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
function isAnswerValidForAnswerInputType(answerInputType) {
|
|
331
|
-
switch (answerInputType) {
|
|
332
|
-
case "x=... ou x=...":
|
|
333
|
-
return `x\\in${texInterval}`;
|
|
334
|
-
case "S={...;...}":
|
|
335
|
-
return `S=${texInterval}`;
|
|
336
|
-
default:
|
|
337
|
-
throw new Error("Unsupported answerInputType: " + answerInputType);
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
return answerInputTypes.some((answerInputType) => isAnswerValidForAnswerInputType(answerInputType));
|
|
326
|
+
//answer is mathbbR
|
|
327
|
+
return ans === answer;
|
|
341
328
|
}
|
|
342
329
|
};
|
|
343
330
|
const getExpOfFEqualsExpOfGEquationQuestion = (optsIn) => {
|
|
@@ -388,10 +388,10 @@ const getPropositions = (n, { answer: _answer, ...identifiers }) => {
|
|
|
388
388
|
}
|
|
389
389
|
return shuffleProps(propositions, n);
|
|
390
390
|
};
|
|
391
|
-
const isAnswerValid = (ans, { answer
|
|
391
|
+
const isAnswerValid = (ans, { answer }) => {
|
|
392
392
|
try {
|
|
393
393
|
const nodeAns = parseAlgebraic(ans);
|
|
394
|
-
const nodeAnswer =
|
|
394
|
+
const nodeAnswer = parseAlgebraic(answer);
|
|
395
395
|
return NodeComparator.isEqualViaRandomSubstitutions(nodeAns, nodeAnswer, 3);
|
|
396
396
|
}
|
|
397
397
|
catch (e) {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Exercise } from "../../../exercises/exercise.js";
|
|
2
|
+
import { GraphIdentifiers } from "../../../math/graphs/graph.js";
|
|
3
|
+
import { GraphEdge, GraphNode } from "../../../math/utils/graphs/graphRenderer.js";
|
|
4
|
+
type Identifiers = {
|
|
5
|
+
graphIds: GraphIdentifiers;
|
|
6
|
+
graphNodes: GraphNode[];
|
|
7
|
+
graphEdges: GraphEdge[];
|
|
8
|
+
};
|
|
9
|
+
export declare const graphsCheckIsConnectedGraph: Exercise<Identifiers>;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=graphsCheckIsConnectedGraph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphsCheckIsConnectedGraph.d.ts","sourceRoot":"","sources":["../../../../src/exercises/math/graphs/graphsCheckIsConnectedGraph.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAaT,MAAM,6BAA6B,CAAC;AAIrC,OAAO,EAGL,gBAAgB,EACjB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,SAAS,EACT,SAAS,EAEV,MAAM,0CAA0C,CAAC;AASlD,KAAK,WAAW,GAAG;IACjB,QAAQ,EAAE,gBAAgB,CAAC;IAG3B,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,UAAU,EAAE,SAAS,EAAE,CAAC;CACzB,CAAC;AA2OF,eAAO,MAAM,2BAA2B,EAAE,QAAQ,CAAC,WAAW,CAiB7D,CAAC"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { addValidProp, tryToAddWrongProp, } from "../../../exercises/exercise.js";
|
|
2
|
+
import { getDistinctQuestions } from "../../../exercises/utils/getDistinctQuestions.js";
|
|
3
|
+
import { GeogebraConstructor } from "../../../geogebra/geogebraConstructor.js";
|
|
4
|
+
import { Point } from "../../../math/geometry/point.js";
|
|
5
|
+
import { GraphConstructor, } from "../../../math/graphs/graph.js";
|
|
6
|
+
import { GraphRenderer, } from "../../../math/utils/graphs/graphRenderer.js";
|
|
7
|
+
import { randint } from "../../../math/utils/random/randint.js";
|
|
8
|
+
import { coinFlip } from "../../../utils/alea/coinFlip.js";
|
|
9
|
+
import { shuffle } from "../../../utils/alea/shuffle.js";
|
|
10
|
+
import { splitIntoRandomChunks } from "../../../utils/arrays/arrayChunks.js";
|
|
11
|
+
import { joinanded } from "../../../utils/strings/joinanded.js";
|
|
12
|
+
import * as Flatten from "@flatten-js/core";
|
|
13
|
+
const getHydrated = (identifiers) => {
|
|
14
|
+
const { graphIds } = identifiers;
|
|
15
|
+
const graph = GraphConstructor.fromIdentifiers(graphIds);
|
|
16
|
+
return {
|
|
17
|
+
graph,
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
const getInstruction = () => {
|
|
21
|
+
return `Un graphe non orienté est représenté ci-dessous.
|
|
22
|
+
Le graphe est-il connexe ?
|
|
23
|
+
*On peut déplacer les points sur la figure.*`;
|
|
24
|
+
};
|
|
25
|
+
const getAnswer = (identifiers) => {
|
|
26
|
+
const { graph } = getHydrated(identifiers);
|
|
27
|
+
return graph.isWeaklyConnected() ? "Oui" : "Non";
|
|
28
|
+
};
|
|
29
|
+
const getHint = () => {
|
|
30
|
+
return `Un graphe non orienté est connexe si et seulement si chaque couple de ses sommets peut être relié par une chaîne.`;
|
|
31
|
+
};
|
|
32
|
+
const getCorrection = (identifiers) => {
|
|
33
|
+
const { graph } = getHydrated(identifiers);
|
|
34
|
+
const arrWeaklyConnectedSubgraph = graph
|
|
35
|
+
.getWeaklyConnectedSubgraphCoveringChainsAsArrIndex()
|
|
36
|
+
.map((chain) => chain.map((index) => graph.vertexNames[index]));
|
|
37
|
+
if (graph.isWeaklyConnected()) {
|
|
38
|
+
const [chain0] = arrWeaklyConnectedSubgraph;
|
|
39
|
+
return `On peut former une chaîne qui relie tous les sommets : ${chain0
|
|
40
|
+
.map((str) => `$${str}$`)
|
|
41
|
+
.join("-")}.
|
|
42
|
+
Le graphe est donc connexe.`;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
return `On ne peut pas former une chaîne qui relie tous les sommets.
|
|
46
|
+
Le graphe contient des sous-graphes disjoints contenant les chaînes ${joinanded(arrWeaklyConnectedSubgraph.map((chain) => chain.map((str) => `$${str}$`).join("-")), ", ", " et ")}.
|
|
47
|
+
Le graphe n'est donc pas connexe.`;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const getGGBOptions = (identifiers) => {
|
|
51
|
+
const { graphNodes, graphEdges } = identifiers;
|
|
52
|
+
const { graph } = getHydrated(identifiers);
|
|
53
|
+
const arrPoint = graphNodes.map(({ label, x, y }) => new Point(label, x, y));
|
|
54
|
+
const pointCommands = arrPoint.flatMap((point) => point.toGGBCommand({
|
|
55
|
+
isFixed: false,
|
|
56
|
+
isSelectionnable: true,
|
|
57
|
+
showLabel: true,
|
|
58
|
+
style: 0,
|
|
59
|
+
size: 8,
|
|
60
|
+
}));
|
|
61
|
+
const edgeCommands = graphEdges.map((e, i) => graph.isDirected
|
|
62
|
+
? `v${i + 1} = Vector(${e.from}, ${e.to})`
|
|
63
|
+
: `s${i + 1} = Segment(${e.from}, ${e.to})`);
|
|
64
|
+
const arrGGBCommandForGraph = [...pointCommands, ...edgeCommands];
|
|
65
|
+
const ggb = new GeogebraConstructor({
|
|
66
|
+
commands: [...arrGGBCommandForGraph],
|
|
67
|
+
fontSize: 16,
|
|
68
|
+
hideAxes: true,
|
|
69
|
+
hideGrid: true,
|
|
70
|
+
});
|
|
71
|
+
return ggb.getOptions({
|
|
72
|
+
coords: ggb.getCoordsForPoints(arrPoint),
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
const getPropositions = (_, { answer }) => {
|
|
76
|
+
const propositions = [];
|
|
77
|
+
["Oui", "Non"].forEach((str) => {
|
|
78
|
+
if (str === answer) {
|
|
79
|
+
addValidProp(propositions, str, "raw");
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
tryToAddWrongProp(propositions, str, "raw");
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
return propositions;
|
|
86
|
+
};
|
|
87
|
+
const createRandomIdentifiers = () => {
|
|
88
|
+
const nbVertices = randint(7, 9);
|
|
89
|
+
const isSimple = true;
|
|
90
|
+
const minDensity = 0.4;
|
|
91
|
+
const isConnected = coinFlip();
|
|
92
|
+
const vertexNames = "ABCDEFGHIJKLM".split("").slice(0, nbVertices);
|
|
93
|
+
const { graph, graphNodes, graphEdges } = (() => {
|
|
94
|
+
let isFound = false;
|
|
95
|
+
let graph;
|
|
96
|
+
let graphNodes;
|
|
97
|
+
let arrGraphEdges;
|
|
98
|
+
while (!isFound) {
|
|
99
|
+
const graphForPoints = GraphConstructor.randomConnected(nbVertices, isSimple, false, minDensity, vertexNames);
|
|
100
|
+
const { nodes: graphNodes0, edges: graphEdges0 } = GraphRenderer.renderToNodesAndEdges(graphForPoints, "circo");
|
|
101
|
+
graphNodes = graphNodes0;
|
|
102
|
+
let arrGraphNodes; //to check overlapping
|
|
103
|
+
[graph, arrGraphEdges, arrGraphNodes] = (() => {
|
|
104
|
+
if (isConnected) {
|
|
105
|
+
return [graphForPoints, [graphEdges0], [graphNodes0]];
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
const arrVertexNamesChunk = splitIntoRandomChunks(shuffle(vertexNames), 3);
|
|
109
|
+
const arrSubGraph = arrVertexNamesChunk.map((vertexNamesChunk) => GraphConstructor.randomConnected(vertexNamesChunk.length, isSimple, false, minDensity, vertexNamesChunk));
|
|
110
|
+
const graph = GraphConstructor.graphByMergingSimpleGraphs(arrSubGraph);
|
|
111
|
+
const arrGraphEdges = arrSubGraph.map((graph) => graph.arrConnection().map(([from, to, _]) => {
|
|
112
|
+
return { from, to };
|
|
113
|
+
}));
|
|
114
|
+
const dictGraphNodes = Object.fromEntries(graphNodes.map((graphNode) => [graphNode.label, graphNode]));
|
|
115
|
+
const arrGraphNodes = arrSubGraph.map((graph) => graph.vertexNames.map((nameVertex) => dictGraphNodes[nameVertex]));
|
|
116
|
+
return [graph, arrGraphEdges, arrGraphNodes];
|
|
117
|
+
}
|
|
118
|
+
})();
|
|
119
|
+
const arrGraphNodes1GraphNodes2 = [...Array(arrGraphNodes.length).keys()]
|
|
120
|
+
.flatMap((i) => [...Array(i + 1).keys()].map((j) => [i, j]))
|
|
121
|
+
.map(([i, j]) => [arrGraphNodes[i], arrGraphNodes[j]]);
|
|
122
|
+
try {
|
|
123
|
+
isFound = arrGraphNodes1GraphNodes2.every(([graphNodes1, graphNodes2]) => {
|
|
124
|
+
const [polygon1, polygon2] = [graphNodes1, graphNodes2].map((graphNodes) => {
|
|
125
|
+
const arrPoint = graphNodes.map(({ x, y }) => new Flatten.Point(x, y));
|
|
126
|
+
const polygon = new Flatten.Polygon(arrPoint);
|
|
127
|
+
return polygon;
|
|
128
|
+
});
|
|
129
|
+
return Flatten.Relations.intersect(polygon1, polygon2);
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
isFound = false;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const graphEdges = arrGraphEdges.reduce((acc, graphEdges) => {
|
|
137
|
+
acc = [...acc, ...graphEdges];
|
|
138
|
+
return acc;
|
|
139
|
+
}, []);
|
|
140
|
+
return { graph: graph, graphNodes: graphNodes, graphEdges };
|
|
141
|
+
})();
|
|
142
|
+
const identifiers = {
|
|
143
|
+
graphIds: graph.toIdentifiers(),
|
|
144
|
+
graphNodes,
|
|
145
|
+
graphEdges,
|
|
146
|
+
};
|
|
147
|
+
return identifiers;
|
|
148
|
+
};
|
|
149
|
+
const getGraphsCheckIsConnectedGraphQuestion = () => {
|
|
150
|
+
const identifiers = createRandomIdentifiers();
|
|
151
|
+
return getQuestionFromIdentifiers(identifiers);
|
|
152
|
+
};
|
|
153
|
+
const getQuestionFromIdentifiers = (identifiers, opts) => {
|
|
154
|
+
const question = {
|
|
155
|
+
answer: getAnswer(identifiers, opts),
|
|
156
|
+
instruction: getInstruction(identifiers, opts),
|
|
157
|
+
answerFormat: "raw",
|
|
158
|
+
identifiers,
|
|
159
|
+
hint: getHint(identifiers, opts),
|
|
160
|
+
correction: getCorrection(identifiers, opts),
|
|
161
|
+
ggbOptions: getGGBOptions(identifiers, opts),
|
|
162
|
+
};
|
|
163
|
+
return question;
|
|
164
|
+
};
|
|
165
|
+
export const graphsCheckIsConnectedGraph = {
|
|
166
|
+
id: "graphsCheckIsConnectedGraph",
|
|
167
|
+
label: "Déterminer si un graphe est connexe",
|
|
168
|
+
isSingleStep: true,
|
|
169
|
+
generator: (nb, opts) => getDistinctQuestions(() => getGraphsCheckIsConnectedGraphQuestion(opts), nb),
|
|
170
|
+
qcmTimer: 60,
|
|
171
|
+
freeTimer: 60,
|
|
172
|
+
getPropositions,
|
|
173
|
+
subject: "Mathématiques",
|
|
174
|
+
getQuestionFromIdentifiers,
|
|
175
|
+
hasHintAndCorrection: true,
|
|
176
|
+
hasGeogebra: true,
|
|
177
|
+
answerType: "QCU",
|
|
178
|
+
};
|
|
@@ -32,7 +32,7 @@ const getHint = () => {
|
|
|
32
32
|
const getCorrection = (identifiers) => {
|
|
33
33
|
const { graph } = getHydrated(identifiers);
|
|
34
34
|
const arrWeaklyConnectedSubgraph = graph
|
|
35
|
-
.
|
|
35
|
+
.getWeaklyConnectedSubgraphCoveringChainsAsArrIndex()
|
|
36
36
|
.map((chain) => chain.map((index) => graph.vertexNames[index]));
|
|
37
37
|
if (graph.isWeaklyConnected()) {
|
|
38
38
|
const [chain0] = arrWeaklyConnectedSubgraph;
|
|
@@ -2,7 +2,7 @@ export * from "./graphsOrderOfGraph.js";
|
|
|
2
2
|
export * from "./graphsDegreeOfVertex.js";
|
|
3
3
|
export * from "./graphsCheckIsVerticesAdjacent.js";
|
|
4
4
|
export * from "./graphsCheckIsSameGraph.js";
|
|
5
|
-
export * from "./
|
|
5
|
+
export * from "./graphsCheckIsConnectedGraph.js";
|
|
6
6
|
export * from "./graphsChainOrPathOfLengthN.js";
|
|
7
7
|
export * from "./edgesNumberFromSummitsDegrees.js";
|
|
8
8
|
export * from "./adjacentMatrixPath.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/exercises/math/graphs/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oCAAoC,CAAC;AACnD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/exercises/math/graphs/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oCAAoC,CAAC;AACnD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,oCAAoC,CAAC;AACnD,cAAc,yBAAyB,CAAC;AACxC,cAAc,sCAAsC,CAAC"}
|
|
@@ -2,7 +2,7 @@ export * from "./graphsOrderOfGraph.js";
|
|
|
2
2
|
export * from "./graphsDegreeOfVertex.js";
|
|
3
3
|
export * from "./graphsCheckIsVerticesAdjacent.js";
|
|
4
4
|
export * from "./graphsCheckIsSameGraph.js";
|
|
5
|
-
export * from "./
|
|
5
|
+
export * from "./graphsCheckIsConnectedGraph.js";
|
|
6
6
|
export * from "./graphsChainOrPathOfLengthN.js";
|
|
7
7
|
export * from "./edgesNumberFromSummitsDegrees.js";
|
|
8
8
|
export * from "./adjacentMatrixPath.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integralFromExpr.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/integration/fromExpr/integralFromExpr.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAiBT,MAAM,6BAA6B,CAAC;AAcrC,OAAO,EAEL,eAAe,EAChB,MAAM,qCAAqC,CAAC;AAe7C,KAAK,WAAW,GAAG;IACjB,QAAQ,EAAE,eAAe,CAAC;IAC1B,aAAa,EAAE,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;IAClD,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;
|
|
1
|
+
{"version":3,"file":"integralFromExpr.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/integration/fromExpr/integralFromExpr.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAiBT,MAAM,6BAA6B,CAAC;AAcrC,OAAO,EAEL,eAAe,EAChB,MAAM,qCAAqC,CAAC;AAe7C,KAAK,WAAW,GAAG;IACjB,QAAQ,EAAE,eAAe,CAAC;IAC1B,aAAa,EAAE,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;IAClD,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAuWF,KAAK,OAAO,GAAG;IACb,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB,CAAC;AA2CF,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,WAAW,EAAE,OAAO,CAe3D,CAAC"}
|
|
@@ -252,7 +252,9 @@ const isIdentifiersQCPassed = (identifiers) => {
|
|
|
252
252
|
const isExploding = (identifiers) => {
|
|
253
253
|
let isExploding = false;
|
|
254
254
|
try {
|
|
255
|
+
//anything that contain exploding simplify()
|
|
255
256
|
getAnswer(identifiers);
|
|
257
|
+
getCorrection(identifiers);
|
|
256
258
|
}
|
|
257
259
|
catch (_) {
|
|
258
260
|
isExploding = true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lineLineRelativePositionsFromParametricLines.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/spaceGeometry/parametricLine/lineLineRelativePositionsFromParametricLines.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAYT,MAAM,6BAA6B,CAAC;AAGrC,OAAO,EAGL,qBAAqB,EACtB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAGL,sBAAsB,EACvB,MAAM,oCAAoC,CAAC;AAgH5C,KAAK,YAAY,GAAG;IAClB,aAAa,EAAE,qBAAqB,CAAC;IACrC,cAAc,EAAE,sBAAsB,CAAC;CACxC,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,eAAe,EAAE,qBAAqB,EAAE,CAAC;IACzC,YAAY,EAAE,YAAY,EAAE,CAAC;CAC9B,CAAC;
|
|
1
|
+
{"version":3,"file":"lineLineRelativePositionsFromParametricLines.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/spaceGeometry/parametricLine/lineLineRelativePositionsFromParametricLines.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAYT,MAAM,6BAA6B,CAAC;AAGrC,OAAO,EAGL,qBAAqB,EACtB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAGL,sBAAsB,EACvB,MAAM,oCAAoC,CAAC;AAgH5C,KAAK,YAAY,GAAG;IAClB,aAAa,EAAE,qBAAqB,CAAC;IACrC,cAAc,EAAE,sBAAsB,CAAC;CACxC,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,eAAe,EAAE,qBAAqB,EAAE,CAAC;IACzC,YAAY,EAAE,YAAY,EAAE,CAAC;CAC9B,CAAC;AA6XF,eAAO,MAAM,4CAA4C,EAAE,QAAQ,CAAC,WAAW,CAoB5E,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { addValidProp, tryToAddWrongProp, } from "../../../../exercises/exercise.js";
|
|
2
2
|
import { getDistinctQuestions } from "../../../../exercises/utils/getDistinctQuestions.js";
|
|
3
3
|
import { ParametricLine } from "../../../../math/geometry/parametricLine.js";
|
|
4
|
-
import { SpacePointConstructor, } from "../../../../math/geometry/spacePoint.js";
|
|
5
|
-
import { SpaceVectorConstructor, } from "../../../../math/geometry/spaceVector.js";
|
|
4
|
+
import { SpacePoint, SpacePointConstructor, } from "../../../../math/geometry/spacePoint.js";
|
|
5
|
+
import { SpaceVector, SpaceVectorConstructor, } from "../../../../math/geometry/spaceVector.js";
|
|
6
6
|
import { nodeBySubstitutingVar } from "../../../../math/utils/functions/functionComposition.js";
|
|
7
7
|
import { randint } from "../../../../math/utils/random/randint.js";
|
|
8
8
|
import { frac } from "../../../../tree/nodes/operators/fractionNode.js";
|
|
@@ -293,8 +293,61 @@ const createRandomIdentifiers = () => {
|
|
|
293
293
|
};
|
|
294
294
|
return identifiers;
|
|
295
295
|
};
|
|
296
|
+
const isIdentifiersQCPassed = (identifiers) => {
|
|
297
|
+
const isExploding = (identifiers) => {
|
|
298
|
+
let isExploding = false;
|
|
299
|
+
try {
|
|
300
|
+
//ensure only one valid proposition
|
|
301
|
+
const n = 4;
|
|
302
|
+
const answer = getAnswer(identifiers);
|
|
303
|
+
const propositions = getPropositions(n, { answer, ...identifiers });
|
|
304
|
+
const nbRightAnswers = propositions.filter((proposition) => proposition.isRightAnswer).length;
|
|
305
|
+
if (nbRightAnswers !== 1) {
|
|
306
|
+
throw new Error("nbRightAnswers !== 1");
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
catch (_) {
|
|
310
|
+
isExploding = true;
|
|
311
|
+
}
|
|
312
|
+
return isExploding;
|
|
313
|
+
};
|
|
314
|
+
return !isExploding(identifiers);
|
|
315
|
+
};
|
|
316
|
+
const createQCPassedIdentifiers = () => {
|
|
317
|
+
let identifiers;
|
|
318
|
+
let counter = -1;
|
|
319
|
+
let isValid = false;
|
|
320
|
+
while (!isValid && counter < 100) {
|
|
321
|
+
counter++;
|
|
322
|
+
const identifiersCandidate = createRandomIdentifiers();
|
|
323
|
+
isValid = isIdentifiersQCPassed(identifiersCandidate);
|
|
324
|
+
if (isValid) {
|
|
325
|
+
identifiers = identifiersCandidate;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
if (!isValid) {
|
|
329
|
+
const vec1 = new SpaceVector("v1", (1).toTree(), (0).toTree(), (0).toTree());
|
|
330
|
+
const vec2 = new SpaceVector("v2", (2).toTree(), (0).toTree(), (0).toTree());
|
|
331
|
+
const A = new SpacePoint("A", (0).toTree(), (1).toTree(), (0).toTree());
|
|
332
|
+
const B = new SpacePoint("B", (0).toTree(), (0).toTree(), (2).toTree());
|
|
333
|
+
const identifiersDefault = {
|
|
334
|
+
spacePointIdsAB: [A, B].map((spacePoint) => spacePoint.toIdentifiers()),
|
|
335
|
+
spaceLineIds: [
|
|
336
|
+
[A, vec1],
|
|
337
|
+
[B, vec2],
|
|
338
|
+
].map(([spacePoint, spaceVector]) => {
|
|
339
|
+
return {
|
|
340
|
+
spacePointIds: spacePoint.toIdentifiers(),
|
|
341
|
+
spaceVectorIds: spaceVector.toIdentifiers(),
|
|
342
|
+
};
|
|
343
|
+
}),
|
|
344
|
+
};
|
|
345
|
+
identifiers = identifiersDefault;
|
|
346
|
+
}
|
|
347
|
+
return identifiers;
|
|
348
|
+
};
|
|
296
349
|
const getLineLineRelativePositionsFromParametricLinesQuestion = () => {
|
|
297
|
-
const identifiers =
|
|
350
|
+
const identifiers = createQCPassedIdentifiers();
|
|
298
351
|
return getQuestionFromIdentifiers(identifiers);
|
|
299
352
|
};
|
|
300
353
|
const getQuestionFromIdentifiers = (identifiers, _opts) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"findNormalVectorFromPlaneEquation.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/spaceGeometry/planes/findNormalVectorFromPlaneEquation.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAgBT,MAAM,6BAA6B,CAAC;AASrC,OAAO,EAEL,eAAe,EAChB,MAAM,qCAAqC,CAAC;AAsF7C,KAAK,WAAW,GAAG;IACjB,oBAAoB,EAAE,eAAe,CAAC;CACvC,CAAC;
|
|
1
|
+
{"version":3,"file":"findNormalVectorFromPlaneEquation.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/spaceGeometry/planes/findNormalVectorFromPlaneEquation.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAgBT,MAAM,6BAA6B,CAAC;AASrC,OAAO,EAEL,eAAe,EAChB,MAAM,qCAAqC,CAAC;AAsF7C,KAAK,WAAW,GAAG;IACjB,oBAAoB,EAAE,eAAe,CAAC;CACvC,CAAC;AAuRF,eAAO,MAAM,iCAAiC,EAAE,QAAQ,CAAC,WAAW,CAmBnE,CAAC"}
|
|
@@ -140,7 +140,9 @@ const getPropositions = (n, { answer, ...identifiers }) => {
|
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
|
+
let counter = -1;
|
|
143
144
|
propWhile(propositions, n, () => {
|
|
145
|
+
counter++;
|
|
144
146
|
const nodeFactorW = randint(-4, 5, [0, 1]).toTree();
|
|
145
147
|
const arr = [nodeA, nodeB, nodeC, nodeD].map((node) => multiply(nodeFactorW, node).simplify({ towardsDistribute: true }));
|
|
146
148
|
{
|
|
@@ -160,6 +162,10 @@ const getPropositions = (n, { answer, ...identifiers }) => {
|
|
|
160
162
|
}
|
|
161
163
|
}
|
|
162
164
|
}
|
|
165
|
+
if (counter > 50) {
|
|
166
|
+
const identifiersWrong = createRandomIdentifiers();
|
|
167
|
+
tryToAddWrongProp(propositions, getAnswer(identifiersWrong));
|
|
168
|
+
}
|
|
163
169
|
});
|
|
164
170
|
return shuffleProps(propositions, n);
|
|
165
171
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"treeTableVEA.d.ts","sourceRoot":"","sources":["../../../src/exercises/vea/treeTableVEA.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"treeTableVEA.d.ts","sourceRoot":"","sources":["../../../src/exercises/vea/treeTableVEA.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,YAAY,GACvB,KAAK,MAAM,EAAE,EAAE,EAAE,EAAE,EACnB,aAAa,MAAM,EAAE,EAAE,EAAE,EAAE,YAiB5B,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { percentVEA } from "./percentVEA.js";
|
|
1
2
|
import { rationalVEA } from "./rationalVEA.js";
|
|
2
3
|
// type Options = {
|
|
3
4
|
// }
|
|
@@ -6,5 +7,6 @@ export const treeTableVEA = (ans, answerTable) => {
|
|
|
6
7
|
//les branches peuvent commuter au sein d'un block
|
|
7
8
|
//les blocks peuvent commuter au sein d'un step
|
|
8
9
|
return ans.every((step, i) => step.every((block, j) => block.every((branch, k) => branch.every((value, l) => value === answerTable[i][j][k][l] ||
|
|
10
|
+
percentVEA(value, answerTable[i][j][k][l]) ||
|
|
9
11
|
rationalVEA(value, answerTable[i][j][k][l])))));
|
|
10
12
|
};
|
|
@@ -26,7 +26,7 @@ export declare class Graph {
|
|
|
26
26
|
densifyUpTo(minDensity: number): Graph;
|
|
27
27
|
undirectedGraph(): Graph;
|
|
28
28
|
isWeaklyConnected(): boolean;
|
|
29
|
-
|
|
29
|
+
getWeaklyConnectedSubgraphCoveringChainsAsArrIndex(): number[][];
|
|
30
30
|
getSomePathsWithNbEdges(nbEdges: number, nbToFindIfPossible: number): number[][];
|
|
31
31
|
/**
|
|
32
32
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../../src/math/graphs/graph.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,MAAM,EAEN,iBAAiB,EAClB,MAAM,uBAAuB,CAAC;AAE/B,8BAAsB,gBAAgB;IACpC,MAAM,CAAC,eAAe,CACpB,UAAU,EAAE,MAAM,EAClB,QAAQ,GAAE,OAAc,EAAE,yBAAyB;IACnD,UAAU,GAAE,OAAe,EAC3B,UAAU,GAAE,MAAa,EAEzB,cAAc,GAAE,MAAM,EAA8B;IA6EtD,MAAM,CAAC,MAAM,CACX,UAAU,EAAE,MAAM,EAClB,QAAQ,GAAE,OAAc,EAAE,yBAAyB;IACnD,UAAU,GAAE,OAAe,EAC3B,UAAU,GAAE,MAAa,EACzB,cAAc,GAAE,MAAM,EAA8B,EACpD,WAAW,GAAE,OAAc;IAkC7B,MAAM,CAAC,WAAW,CAChB,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,EAAE,YAA4B,EACpD,UAAU,EAAE,OAAO;IAuErB,MAAM,CAAC,0BAA0B,CAAC,QAAQ,EAAE,KAAK,EAAE;IAgCnD,MAAM,CAAC,uBAAuB,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK;IA0BnD,MAAM,CAAC,eAAe,CAAC,WAAW,EAAE,gBAAgB;CAKrD;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,qBAAa,KAAK;IAChB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,OAAO,CAAC;gBACR,WAAW,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,OAAO;IAMpE,aAAa;IASb,eAAe,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAmB1D,aAAa,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAc5C,OAAO,IAAI,MAAM;IAIjB,WAAW,CAAC,UAAU,EAAE,MAAM;IAc9B,eAAe,IAAI,KAAK;IASxB,iBAAiB,IAAI,OAAO;IAoC5B,
|
|
1
|
+
{"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../../src/math/graphs/graph.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,MAAM,EAEN,iBAAiB,EAClB,MAAM,uBAAuB,CAAC;AAE/B,8BAAsB,gBAAgB;IACpC,MAAM,CAAC,eAAe,CACpB,UAAU,EAAE,MAAM,EAClB,QAAQ,GAAE,OAAc,EAAE,yBAAyB;IACnD,UAAU,GAAE,OAAe,EAC3B,UAAU,GAAE,MAAa,EAEzB,cAAc,GAAE,MAAM,EAA8B;IA6EtD,MAAM,CAAC,MAAM,CACX,UAAU,EAAE,MAAM,EAClB,QAAQ,GAAE,OAAc,EAAE,yBAAyB;IACnD,UAAU,GAAE,OAAe,EAC3B,UAAU,GAAE,MAAa,EACzB,cAAc,GAAE,MAAM,EAA8B,EACpD,WAAW,GAAE,OAAc;IAkC7B,MAAM,CAAC,WAAW,CAChB,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,EAAE,YAA4B,EACpD,UAAU,EAAE,OAAO;IAuErB,MAAM,CAAC,0BAA0B,CAAC,QAAQ,EAAE,KAAK,EAAE;IAgCnD,MAAM,CAAC,uBAAuB,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK;IA0BnD,MAAM,CAAC,eAAe,CAAC,WAAW,EAAE,gBAAgB;CAKrD;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,qBAAa,KAAK;IAChB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,OAAO,CAAC;gBACR,WAAW,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,OAAO;IAMpE,aAAa;IASb,eAAe,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAmB1D,aAAa,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAc5C,OAAO,IAAI,MAAM;IAIjB,WAAW,CAAC,UAAU,EAAE,MAAM;IAc9B,eAAe,IAAI,KAAK;IASxB,iBAAiB,IAAI,OAAO;IAoC5B,kDAAkD,IAAI,MAAM,EAAE,EAAE;IAuGhE,uBAAuB,CACrB,OAAO,EAAE,MAAM,EACf,kBAAkB,EAAE,MAAM,GACzB,MAAM,EAAE,EAAE;IAmCb;;;;OAIG;IACH,oBAAoB,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,EAAE;IAqBxD,wBAAwB,CAAC,gBAAgB,EAAE,MAAM;IAUjD,+BAA+B,CAC7B,gBAAgB,EAAE,MAAM,EACxB,kBAAkB,EAAE,OAAO;IAmB7B,WAAW,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,OAAO;IAQ7C,eAAe;IAWf,MAAM,CAAC,MAAM,EAAE,KAAK;CAQrB"}
|
package/lib/math/graphs/graph.js
CHANGED
|
@@ -265,44 +265,100 @@ export class Graph {
|
|
|
265
265
|
return visited.every((v) => v);
|
|
266
266
|
//AI CODE (Edge) }
|
|
267
267
|
}
|
|
268
|
-
|
|
268
|
+
getWeaklyConnectedSubgraphCoveringChainsAsArrIndex() {
|
|
269
269
|
const adjMatrix = (this.isDirected ? this.undirectedGraph() : this)
|
|
270
270
|
.adjacencyMatrix()
|
|
271
271
|
.elements.map((row) => row.map((elt) => elt.evaluate()));
|
|
272
|
-
//AI CODE (Edge) {
|
|
273
|
-
// Validate input
|
|
274
|
-
if (!Array.isArray(adjMatrix) || adjMatrix.length === 0) {
|
|
275
|
-
throw new Error("Adjacency matrix must be a non-empty 2D array.");
|
|
276
|
-
}
|
|
277
272
|
const n = adjMatrix.length;
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
273
|
+
const linked = (i, j) => i !== j &&
|
|
274
|
+
((adjMatrix[i]?.[j] ?? 0) !== 0 || (adjMatrix[j]?.[i] ?? 0) !== 0);
|
|
275
|
+
// Voisinage non orienté
|
|
276
|
+
const neighbors = Array.from({ length: n }, (_, i) => {
|
|
277
|
+
const list = [];
|
|
278
|
+
for (let j = 0; j < n; j++)
|
|
279
|
+
if (linked(i, j))
|
|
280
|
+
list.push(j);
|
|
281
|
+
return list;
|
|
282
|
+
});
|
|
283
|
+
// 1. Composantes connexes
|
|
284
|
+
const seen = new Array(n).fill(false);
|
|
285
|
+
const components = [];
|
|
286
|
+
for (let start = 0; start < n; start++) {
|
|
287
|
+
if (seen[start])
|
|
288
|
+
continue;
|
|
289
|
+
const component = [];
|
|
290
|
+
const stack = [start];
|
|
291
|
+
seen[start] = true;
|
|
292
|
+
while (stack.length > 0) {
|
|
293
|
+
const node = stack.pop();
|
|
294
|
+
component.push(node);
|
|
295
|
+
for (const nb of neighbors[node]) {
|
|
296
|
+
if (!seen[nb]) {
|
|
297
|
+
seen[nb] = true;
|
|
298
|
+
stack.push(nb);
|
|
299
|
+
}
|
|
290
300
|
}
|
|
291
301
|
}
|
|
302
|
+
components.push(component.sort((a, b) => a - b));
|
|
292
303
|
}
|
|
293
|
-
//
|
|
294
|
-
|
|
295
|
-
if (
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
304
|
+
// 2. Chaîne couvrant une composante
|
|
305
|
+
const coveringChain = (component) => {
|
|
306
|
+
if (component.length === 1)
|
|
307
|
+
return [...component];
|
|
308
|
+
// Arbre couvrant en profondeur (donne des branches longues)
|
|
309
|
+
const tree = new Map(component.map((v) => [v, []]));
|
|
310
|
+
const inTree = new Set([component[0]]);
|
|
311
|
+
const grow = (u) => {
|
|
312
|
+
for (const v of neighbors[u]) {
|
|
313
|
+
if (!inTree.has(v)) {
|
|
314
|
+
inTree.add(v);
|
|
315
|
+
tree.get(u).push(v);
|
|
316
|
+
tree.get(v).push(u);
|
|
317
|
+
grow(v);
|
|
318
|
+
}
|
|
301
319
|
}
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
320
|
+
};
|
|
321
|
+
grow(component[0]);
|
|
322
|
+
// Sommet le plus éloigné (BFS dans l'arbre) + parents pour remonter la branche
|
|
323
|
+
const farthest = (src) => {
|
|
324
|
+
const parent = new Map([[src, -1]]);
|
|
325
|
+
const queue = [src];
|
|
326
|
+
for (let i = 0; i < queue.length; i++) {
|
|
327
|
+
for (const v of tree.get(queue[i])) {
|
|
328
|
+
if (!parent.has(v)) {
|
|
329
|
+
parent.set(v, queue[i]);
|
|
330
|
+
queue.push(v);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return { last: queue[queue.length - 1], parent };
|
|
335
|
+
};
|
|
336
|
+
// Diamètre de l'arbre : de a à b
|
|
337
|
+
const a = farthest(component[0]).last;
|
|
338
|
+
const { last: b, parent } = farthest(a);
|
|
339
|
+
const onDiameter = new Set();
|
|
340
|
+
for (let v = b; v !== -1; v = parent.get(v))
|
|
341
|
+
onDiameter.add(v);
|
|
342
|
+
// Parcours depuis a : les sous-arbres annexes d'abord (avec retour),
|
|
343
|
+
// la branche du diamètre en dernier (sans retour)
|
|
344
|
+
const chain = [];
|
|
345
|
+
const visit = (u, from) => {
|
|
346
|
+
chain.push(u);
|
|
347
|
+
const children = tree
|
|
348
|
+
.get(u)
|
|
349
|
+
.filter((v) => v !== from)
|
|
350
|
+
.sort((x, y) => Number(onDiameter.has(x)) - Number(onDiameter.has(y)));
|
|
351
|
+
for (const child of children) {
|
|
352
|
+
visit(child, u);
|
|
353
|
+
if (!onDiameter.has(child))
|
|
354
|
+
chain.push(u); // retour arrière
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
visit(a, -1);
|
|
358
|
+
// Normalisation : commencer par la plus petite extrémité
|
|
359
|
+
return chain[0] > chain[chain.length - 1] ? chain.reverse() : chain;
|
|
360
|
+
};
|
|
361
|
+
return components.map(coveringChain);
|
|
306
362
|
}
|
|
307
363
|
getSomePathsWithNbEdges(nbEdges, nbToFindIfPossible) {
|
|
308
364
|
const n = nbEdges;
|