diff --git a/Doc/source/ecrire.rst b/Doc/source/ecrire.rst new file mode 100644 index 00000000..565d1b13 --- /dev/null +++ b/Doc/source/ecrire.rst @@ -0,0 +1,500 @@ +.. _ecrire: + +=================================== +Tutoriel : Créer un nouvel exercice +=================================== + +Cette article décrit la procédure pour créer un nouvel exercice pour Pyromaths. Nous prendrons comme exemple la création d'un exercice de résolution d'équations du premier degré du type :math:`ax+b=cx+d` où les nombres :math:`a`, :math:`b`, :math:`c`, :math:`d` sont des entiers relatifs. + +.. note:: + + Certains termes techniques anglais + (comme `template`, `merge`, etc.) + n'ont volontairement pas été traduits. + Cette documentation renvoit à d'autres documentation en anglais, + et pour que la personne lisant ces lignes s'y retrouve d'une documentation à l'autre, + nous avons fait le choix de conserver les termes anglais plutôt que d'utiliser leur équivalent français. + +.. note:: + + Cette documentation a été écrite en se mettant à la place d'une personne utilisant GNU/Linux. + Il est également possible d'écrire un nouvel exercice depusi Windows ou MacOS, + mais certaines commandes décrites dans ce document changent un peu. + À vous de les adapter. + +.. contents:: + :local: + :depth: 1 + +Préambule +========= + +Les personnes pressées peuvent jeter un œil à deux exercices implémentés dans Pyromaths : + +- un exemple simple (avec très peu de cas particuliers) : la recherche d'état stable. + + - :download:`code Python <../../src/pyromaths/ex/lycee/matrices.py>` + - :download:`template de l'énoncé <../../data/ex/templates/EtatStableSysteme2-statement.tex>` + - :download:`template de la solution <../../data/ex/templates/EtatStableSysteme2-answer.tex>` + +- un exemple plus complexe (avec cas particuliers) : bilan sur les polynômes du second degré en seconde. + + - :download:`code Python <../../src/pyromaths/ex/lycee/seconddegre.py>` ; + - :download:`template de l'énoncé <../../data/ex/templates/BilanTrinomeSansDiscriminant-statement.tex>` ; + - :download:`template de la solution <../../data/ex/templates/BilanTrinomeSansDiscriminant-answer.tex>`. + + +Prérequis +========= + +Loi +--- + +Pyromaths est publié sous licence publique GNU version 3 (`GPLv3 `__). Si vous souhaitez contribuer à Pyromaths en partageant votre exercice, celui-ci devra impérativement être également publié sous cette même licence. + +Connaissances +------------- + +Créer un exercice pour Pyromaths nécessite de savoir utiliser un minimum : + +- :math:`LaTeX` ; +- Python (version 2) ; +- git. + +Une connaissance de la bibliothèque Python `jinja2 `__ est un plus, mais les bases s'apprennent rapidement et sont décrites plus loins dans ce document. + +Outils +------ + +À part `git `__, tous les outils nécessaires pour créer un exercice sont des dépendances de Pyromaths. `Installez `__, et faites fonctionner Pyromath : les outils nécessaires pour ce tutoriel seront alors disponibles. + +Environnement de travail +======================== + +Commençons par télécharger les sources de Pyromaths, en utilisant le logiciel `git`. Si vous avez un compte `Github `__, utilisez : + +.. code-block:: shell + + $ git clone git@github.com:Pyromaths/pyromaths.git + +Si vous n'avez pas de tel compte, utilisez : + +.. code-block:: shell + + $ git clone https://github.com/Pyromaths/pyromaths.git + +Puis déplacez vous dans le répertoire `pyromaths` ainsi créé. À partir de maintenant, sauf mention contraire, toutes les commandes sont à exécuter depuis ce répertoire. + +La version de développement de Pyromaths se trouve dans la branche `develop` : + +.. code-block:: shell + + $ git checkout develop + +Il sera plus confortable, pour vous comme pour nous, que vous travailliez dans une branche séparée, par exemple `EquationPremierDegre` : + +.. code-block:: shell + + $ git branch EquationPremierDegre + $ git checkout EquationPremierDegre + +Brouillon +========= + +La première étape est d'écrire un exercice en :math:`LaTeX`, sans passer par Python, sans aléa : juste pour observer le rendu final. Utilisez l'outil :ref:`pyromaths-cli.py `. + +.. code-block:: shell + + $ utils/pyromaths-cli.py dummy + +Cette commande a pour effet de créer un modèle d'exercice, sous la forme d'un PDF qui est affiché à l'écran, et d'un fichier :math:`LaTeX` :file:`exercices.tex`. + +Déplacez ce fichier dans un répertoire temporaire, et modifiez-le pour écrire le sujet de votre énoncé, à la place de ``ÉNONCÉ DE L'EXERCICE`` et ``CORRIGÉ DE L'EXERCICE``. Ne vous souciez pas de la manière dont cela sera intégré à Pyromaths ; ne vous souciez pas de la manière dont l'aléa sera intégré : nous verrons cela plus tard. C'est l'occasion de travailler la formulation de l'énoncé et de la solution pour qu'ils soient le plus clair possible. + +Ne modifiez que les lignes qui correspondent à l'énoncé ou au corrigé. En particulier, ne modifiez pas le préambule. + +Ce fichier doit être compilé avec ``latex``, puis converti en pdf avec ``dvipdf``. À la fin de cette étape, nous obtenons l'énoncé suivant (:download:`tex `, :download:`pdf `). + +.. literalinclude:: ecrire/1/exercices.tex + :language: latex + :linenos: + :lineno-start: 115 + :lines: 115-146 + +Première version (sans aléa) +============================ + +Nous allons maintenant intégrer cet exercice à Pyromaths, sans aléa pour le moment. + +Choisissez un identifiant pour votre exercice : un nom composé uniquement de lettres sans accents et de chiffres, sans espaces, comme `ConversionDegresRadians`, `TheoremeDePythagore`, `CoordonneesDuMilieu`, etc. Pour notre exemple, nous choissons `EquationPremierDegre` (qui sera décliné en `EquationPremierDegre2`, `EquationPremierDegre3`, etc. au fil de ce tutoriel). + +Code Python +----------- + +Le code Python de l'exercice doit être placé dans un des sous-dossiers de ``src/pyromaths/ex/``. Dans notre cas, ce sera ``src/pyromaths/ex/troisiemes``. Ensuite, modifiez un des fichiers `.py` déjà existant, ou créez-en un nouveau. Gardez une certaine logique : un exercice sur Pythagore a sa place dans le même fichier qu'un autre exercice sur Pythagore ; un exercice de trigonométrie n'a pas sa place dans un fichier ``matrices.py``. Dans notre cas, nous crréons un nouveau fichier contenant le code suivant. + +.. literalinclude:: ecrire/2/equation2.py + :linenos: + +Modifiez les parties suivantes : + +- ligne 8 : votre nom, et l'année courante ; +- ligne 29 : l'identifiant de l'exercice ; +- ligne 31 : la description de l'exercice ; +- ligne 32 : le niveau de l'exercice (le nombre avant le point sert à trier les niveaux ; celui après le point est le texte qui sera visible à l'utilisateur). + +Code :math:`LaTeX` +------------------ + +Le code :math:`LaTeX`, quant à lui, doit être placé dans le répertoire ``data/ex/templates``, dans deux fichiers au nom de votre exercices. Reprenez votre fichier :download:`exercices.tex `, et extrayez les lignes correspondant à l'énoncé, que vous écrivez dans le fichier :download:`EquationPremierDegre2-statement.tex `, et celles correspondant au corrigé dans le fichier :download:`EquationPremierDegre2-answer.tex `. + +L'énoncé est alors dans le fichier :download:`EquationPremierDegre2-statement.tex `. + +.. literalinclude:: ecrire/2/EquationPremierDegre2-statement.tex + :language: latex + :linenos: + +Le corrigé est dans le fichier :download:`EquationPremierDegre2-answer.tex ` + +.. literalinclude:: ecrire/2/EquationPremierDegre2-answer.tex + :language: latex + :linenos: + +Génération de l'exercice +------------------------ + +Vous pouvez maintenant tester la génération de votre exercice, en exécutant la commande suivante. + +.. code-block:: shell + + $ utils/pyromaths-cli.py generate EquationPremierDegre2 + +Vous obtenez alors le fichier :download:`exercice.pdf `. + +Bilan +----- + +Nous avons écrit notre premier exercice, qui est intégré à Pyromaths. Par contre, il n'y a pas d'aléa : les valeurs numériques sont toujours les mêmes. Cela sera résolu dans la partie suivante. + +Ajout du hasard +=============== + +Dans cette partie, pour générer l'exercice et suivre votre travail, la commande à utiliser est la suivante. + +.. code-block:: shell + + $ utils/pyromaths-cli.py generate EquationPremierDegre3:2 + +Remarquez que par rapport à la commande utilisée dans la partie précédente, un ``:2`` a été ajouté à la fin de la ligne. Il correspond à la graine (`seed`) du générateur pseudo-aléatoire. + +.. note:: + + Un ordinateur ne sait pas générer du hasard. Il faut ruser. + + Dans notre exercice, nous avons besoin de nombres entiers entre 0 et 9. Pour avoir des nombres aléatoires, à chaque fois que nous utilisons un nombre aléatoire, nous prenons une décimale de π : d'abord `1`, puis `4`, puis `1`, puis `5`, et ainsi de suite. Cela à l'aire aléatoire à première vue, mais deux exécutions successives donneront exactement le même exercice. Améliorons cela. + + Nous gardons le même système, mais au lieu de commencer à la première décimale de π, nous utilisons désormais sur l'heure courante : si le programme est lancé à 13h37, nous utilisons alors les décimales de π à partir de la 1337e. Ainsi, deux exécutions successives donneront deux exercices différents. + + C'est mieux. Mais quand nous créerons notre exercices, nous allons générer encore et encore un exercice, et nous aimerions toujours générer le même (cela facilitera le développement, pour ne pas être perturbé par des valeurs numériques qui changent ; pour qu'un bug introduit par une valeur numérique spécifique n'apparaisse et ne disparaisse pas aléatoirement). Du coup, nous imposons le début de la séquence aléatoire : c'est la signification du ``:2`` ajouté à la fin de la ligne de commande. + + C'est un peu plus compliqué en réalité, mais dans les grande lignes, c'est ainsi qu'un ordinateur génère du hasard. Plus d'informations, par exemple, dans l'article de Wikipédia `Pseudorandom generator `__. + +Si nous voulons générer un autre exercice, il suffit de transformer le ``EquationPremierDegre3:2`` en ``EquationPremierDegre3:1729``, ``EquationPremierDegre3:0123456789``, ou n'importe quel nombre de votre choix. + +Code Python +----------- + +Du côté de Python, il faut tirer au hasard quatre nombres entiers entre -10 et 10 (sauf 0 et 1, qui sont des cas particuliers), et les rendre disponible depuis le code :math:`LaTeX`. Cela se fait avec le contexte. Toutes les variables présentes dans ce dictionnaire seront accessibles depuis le `template` jinja2. + +.. literalinclude:: ecrire/3/equation3.py + :linenos: + :lineno-start: 27 + :lines: 27-44 + +Code :math:`LaTeX` +------------------ + +Du côté de :math:`LaTeX`, nous allons profiter de la bibliothèque jinja2 pour utiliser les variables rendues disponibles dans le contexte. + +.. note:: + + Cette note se veut une courte introduction à Jinja2. Pour aller plus loins, rendez-vous sur `le site du projet `__. + + Un template jinja2 est du code :math:`LaTeX` qui sera reproduit tel quel dans le document final, sauf que : + + - les variables peuvent être évaluées avec des doubles parenthèses. Pour insérer la valeur de la variable ``a`` du contexte, il faut utiliser ``(( a ))`` ; + - des structures de contrôle (condition, boucle) peuvent être utilisées entourées par ``(*`` et ``*)``. + + Notons que les chaînes définissant ces blocs ont été modifiées par rapport aux chaînes initiales, car trop proches de la syntaxe :math:`LaTeX`. Ceci est documenté sur `le site officiel `__, et mis en œuvre dans la classe :class:`pyromaths.ex.Jinja2Exercice`. + + .. literalinclude:: ../../src/pyromaths/ex/__init__.py + :linenos: + :lineno-start: 200 + :lines: 200-215 + +L'énoncé est assez simple : il suffit de faire appel aux variables du contexte. + +.. literalinclude:: ecrire/3/EquationPremierDegre3-statement.tex + :language: latex + :linenos: + +Dans ce code, ``(( a ))`` et ``(( c ))`` sont remplacés par les valeurs des variables ``a`` et ``c`` du contexte, et ``(( "%+d"|format(b) ))`` est remplacé par le résultat du code Python ``"%+d" % b``, ce qui a pour effet d'écrire l'entier ``b`` *avec son signe* (qu'il soit positif ou négatif). + +La rédaction du corrigé se fait de la même manière, en remarquant que le code ``(( d - b ))``, par exemple, est remplacé par le résultat du calcul ``d - b``. Notons également l'utilisation de ``(( ((d-b)/(a-c)) | round(2) ))``, qui permet d'arrondir le résultat du calcul ``(d-b)/(a-c)`` à deux chiffres après la virgule. L'ensemble de ces fonctions (``format``, ``round``, etc.), que jinja2 appelle `filters`, est décrit `dans la documentation officielle `__. + +.. literalinclude:: ecrire/3/EquationPremierDegre3-answer.tex + :language: latex + :linenos: + +Débuggage +--------- + +Durant cette phase, il est probable que le code :math:`LaTeX` produit soit un peu compliqué, et contienne des erreurs. Il serait alors pratique de pouvoir observer (si ce n'est plus) ce code avant compilation. C'est possible avec l'option ``--pipe`` de :ref:`pyromaths-cli.py `. + +Cette option permet de définir des commandes (du shell) qui seront executées sur le fichier :math:`LaTeX`, avant sa compilation. Par exemple : + +- ``--pipe cat`` exécute ``cat FICHIER.tex``, et permet d'observer le fichier avant compilation ; +- ``--pipe vim`` exécute ``vim FICHIER.tex``, et permet de modifier le fichier avant compilation ; +- ``--pipe "cp {} draft.tex"`` exécute ``cp FICHIER.tex draft.tex``, et permet d'obtenir une copie du fichier :math:`LaTeX`, si le problème est trop complexe pour pouvoir être résolu avec les options ci-dessous ; +- et n'importe quelle commande du shell peut-être exécutée, au gré de votre imagination. + +Bilan +----- + +Nous avons produit l'exercice :download:`exercice.pdf `. Il fonctionne, mais il y a trois problèmes dans le corrigé : premièrement, alors que la solution est exacte, le signe :math:`\approx` est utilisé ; ensuite, bien que la solution soit entière, le code a produit ``3,0`` plutôt que ``3`` ; enfin, un troisième problème n'apparaît pas ici, mais sera expliqué et résolu plus loin dans ce document. + +.. figure:: ecrire/3/corrige.png + :align: center + +.. _ecrire-facteur: + +Structures de contrôle +====================== + +Dans la correction de l'exercice, le signe utilisé pour donner la solution est :math:`\approx`, que la solution soit exacte ou non. Cela peut être corrigé avec une structure de contrôle. + +Structures de contrôles +----------------------- + +Pour corriger le second, il suffit de tester si la solution est exacte ou non. Pour cela, nous testons si la solution (multipliée par 100) est égale à la partie entière de la solution, multipliée par 100 elle aussi. + +.. literalinclude:: ecrire/4/EquationPremierDegre4-answer.tex + :language: latex + :lineno-start: 9 + :lines: 9-13 + +Pour tester si la solution est exacte, nous aurions aussi pu définir un `test personnalisé `__. + +D'autres structures de contrôle sont disponibles ; elles sont détaillées dans `la documentation officielle `__. + +Bilan +----- + +La source de la correction est maintenant celle-ci. + +.. literalinclude:: ecrire/4/EquationPremierDegre4-answer.tex + :linenos: + :language: latex + +Elle produit :download:`ce résultat `. Reste à traiter le problème de l'affichage des nombres entiers (``3,0`` au lieu de ``3``). + +Affichage des nombres, et `filters` personnalisés +================================================= + +Problème +-------- + +Afficher un nombre n'est pas aussi simple qu'il n'y paraît. Dans notre exemple, le code produit ``3,0`` plutôt que ``3``, à cause de Python qui manipule des flottants, et écrit donc la première version pour insister sur le type flottant plutôt qu'entier. Mais il y a bien pire. + +Supposons par exemple que nous voulons afficher l'équation de la droite d'équation :math:`y=ax+b`, où :math:`a` et :math:`b` sont des nombres entiers. A priori, utiliser ``y=\numprint{(( a ))}x+\numprint{(( b ))}`` dans notre template devrait faire l'affaire, non ? Non. Plusieurs problèmes peuvent se poser. + +- Si :math:`a=0` et :math:`b=2`, nous obtenons ``y=0x+2`` au lieu de ``y=2``. +- Si :math:`a=1` et :math:`b=2`, nous obtenons ``y=1x+2`` au lieu de ``y=x+2``. +- Si :math:`a=-1` et :math:`b=2`, nous obtenons ``y=-1x+2`` au lieu de ``y=-x+2``. +- Si :math:`a=2` et :math:`b=0`, nous obtenons ``y=2x+0`` au lieu de ``y=2x``. +- Si :math:`a=2` et :math:`b=-2`, nous obtenons ``y=2x+-2`` au lieu de ``y=2x-2``. +- Si :math:`a=0` et :math:`b=0`, nous obtenons ``y=0x+0`` au lieu de ``y=0``. + +Cela fait beaucoup de cas à traiter. Tous (sauf le dernier) peuvent être résolu en utilisant le *filter* :func:`pyromaths.outils.jinja2.facteur`. + +`Filters` personnalisés +----------------------- + +Un `filter` est une fonction qui peut être transmise au template afin d'être appelée depuis le template. Ils sont décrits sur `la documentation officielle `__. + +.. currentmodule:: pyromaths.outils.jinja2 + +Une fonction du module :mod:`pyromaths.outils.jinja2` existe pour corriger les problèmes cités plus haut : :func:`facteur` permet de formatter correctement les facteurs dans une expression. Encore faut-il que cette fonction soit accessible depuis le `template` :math:`LaTeX`. + +Ajoutons la méthode suivante à la classe :class:`~pyromaths.ex.troisiemes.equation.EquationPremierDegre4` : + +.. literalinclude:: ecrire/5/equation5.py + :linenos: + :lineno-start: 47 + :lines: 47-53 + +Celle-ci a pour effet d'ajouter à l'environnement jinja2 la fonction :func:`facteur` comme un `filter`, qui est alors accessible depuis le `template`. Dans cette ligne, le nombre :math:`\frac{d-b}{a-c}` est arrondi à deux décimales après la virgule, et affiché en respectant les règles françaises (notamment avec une virgule comme séparateur décimal). + +.. literalinclude:: ecrire/5/EquationPremierDegre5-answer.tex + :language: latex + :lineno-start: 14 + :lines: 14 + +Un `filter` n'est rien d'autre qu'une fonction python. D'autres `filters` peuvent donc être définis et utilisés à votre convenance. + +.. note:: + + Pour revenir au problème du début de cette partie, afficher l'équation d'une droite peut se faire en utilisant le code suivant, qui prend en charge tous les cas particuliers décrits plus haut. + + .. code-block:: latex + + (* if a == 0 and b == 0 *) + y = 0 + (* else *) + y = (( a|facteur("*x") )) (( b|facteur("*so") )) + (* endif *) + + - Si :math:`a=2` et :math:`b=3`, le code :math:`\LaTeX` produit est ``y=2x+3``. + - Si :math:`a=0` et :math:`b=0`, le test ``if`` permet d'afficher la bonne équation. + - Si :math:`a=0` l'option ``"*x"`` permet de ne rien afficher. + - Si :math:`a=1` l'option ``"*x"`` permet d'afficher ``x`` plutôt que ``1x``. + - Si :math:`a=-1` l'option ``"*x"`` permet d'afficher ``x`` plutôt que ``-1x``. + - Si :math:`b=0`, l'option ``"*so"`` n'affiche pas l'ordonnée à l'origine. + - Si :math:`b=-2`, le signe négatif est correctement affiché. + + Des exemples d'utilisation de cette fonction sont fournis avec :func:`sa documentation `. + +Bilan +----- + +Nous obtenons :download:`cet exercice `. Il est quasiment terminé, non ? Non ! Car voici… *(musique terrifiante)* les cas particuliers… + +Gestion des cas particuliers +============================ + +Deux problèmes subsistent. + +- Dans certains cas (par exemple ``utils/pyromaths-cli.py generate EquationPremierDegre4:15``, les deux coefficients :math:`a` et :math:`c` de l'équation :math:`ax+b=cx+d` sont égaux, et notre programme, qui suppose qu'il existe une solution unique, essaye de la calculer, et divise par 0. +- Lorsque nous arrivons (par exemple) à l'équation ``2x=6``, l'étape suivante est de diviser les deux membres par deux. Mais cette étape est inutile lorsque, par hasard, ``x`` est multiplié par 1, comme dans l'exemple suivant. + + .. figure:: ecrire/6/1x.png + :align: center + +Il y a trois manières de résoudre ces problèmes. Elles ne sont pas exclusives, et il en existe d'autres. + +Prise en compte avec Python +--------------------------- + +Dans ce cas-là, la résolution se fait en Python. Le code :math:`LaTeX` est donc réduit au minimum. + +.. literalinclude:: ecrire/6.1/EquationPremierDegre61-answer.tex + :linenos: + :language: latex + +C'est en Python, en revanche, que tous les cas particuliers sont traités. Nous avons donc ajouté deux variables au contexte : ``calculs`` contenant la liste des étapes de calcul, et ``conclusion`` contenant la phrase de conclusion. + +.. literalinclude:: ecrire/6.1/equation61.py + :linenos: + :lineno-start: 32 + :lines: 32-80 + +Le code est plus complet, mais plus difficile à lire. + +Prise en compte avec Jinja2 +--------------------------- + +Puisque les cas particuliers sont traités avec Jinja2, le code Python est réduit au minimum (il n'a pas été modifié depuis la version précédente). + +.. literalinclude:: ecrire/6.2/equation62.py + :linenos: + :lineno-start: 32 + :lines: 32-53 + +Le code :math:`LaTeX`, en revanche, est plus fourni. + +.. literalinclude:: ecrire/6.2/EquationPremierDegre62-answer.tex + :language: latex + +Encore une fois, le code est plus complet, mais plus difficile à lire. + +Suppression des cas particuliers +-------------------------------- + +La méthode la plus confortable dans les cas simples est d'exclure les cas particuliers. Pour cela, au lieu d'accepter n'importe quel tirage de nos coefficients, s'ils ne nous conviennent pas, nous recommençons. + +Avec cette méthode, pas besoin de toucher aux `templates` : nous modifions simplement le constructeur de la classe :class:`~pyromaths.ex.troisiemes.equation.EquationPremierDegre63`. + +.. literalinclude:: ecrire/6.3/equation63.py + :linenos: + :lineno-start: 37 + :lines: 37-59 + +Bilan +----- + +Supprimer les cas particuliers est sans doute le plus confortable pour écrire un exercice. Mais c'est aussi moins riche pour les élèves. + +Il n'y a pas de meilleure solution ici ; faites ce qui vous paraît le moins pire. + +Finalisation +============ + +L'exercice est bientôt prêt à être publié. + +Créer les vignettes +------------------- + +Si vous lancez la version graphique de Pyromaths, vous remarquez que l'aperçu de votre exercice n'est pas disponible ; il manquera aussi sur la `version en ligne `__. C'est normal : il n'a pas encore été généré. Corrigez cela avec la commande suivante. + +.. code-block:: shell + + $ utils/creer-vignettes.py + +Cette commande détecte les vignettes manquantes (ou celles pour lesquelles l'exercice a été modifié), et les génère. + +Ajouter des tests +----------------- + +Dans quelques mois ou années, quelqu'un (peut-être vous) voudrait modifier quelque chose de Pyromaths, en se demandant si cela va « casser » un exercice. Pour être sûr que votre exercice soit préservé, il serait sage de le tester. L'ajout d'un test se fait avec la commande suivante. + +.. code-block:: shell + + $ utils/pyromaths-cli.py test create EquationPremierDegre + +Cette commande va générer un exercice, l'afficher (dans un lecteur de pdf externe), et vous demander confirmation. Si l'exercice est correct, validez, et cet exercice sera ajouté aux tests. + +Si vous voulez ajouter un exercice particulier (car vous savez qu'il correspond à un cas très particulier), ajouter ce numéro d'exercice à votre commande (1729 ici). + +.. code-block:: shell + + $ utils/pyromaths-cli.py test create EquationPremierDegre:1729 + +Plus tard, pour vérifier que votre exercice n'a pas été modifier, vérifiez les tests en utilisant ce même programme. + +.. code-block:: shell + + $ utils/pyromaths-cli.py test check + +Publication ! +============= + +Ajout des fichiers créés ou modifiés +------------------------------------ + +Utilisez ``git add`` pour ajouter les fichiers créés ou modifiés. À priori, cela concerne au moins : + +- un fichier python contenant la classe de votre exercice (dans un des dossiers ``src/pyromaths/ex/*``) ; +- deux fichiers de template :math:`LaTeX` (dans le dossier ``data/ex/templates``) ; +- la vignette, et le fichier ``md5sum.json`` (dans le dossier ``data/ex/img``) ; +- les fichiers de test (dans le dossier ``data/ex/tests``) ; +- et peut-être d'autre, selon votre travail. + +Proposition de l'exercice +------------------------- + +Il ne reste qu'à nous proposer votre exercice, de préférence en utilisant une *pull request* sur Github, à défaut en prenant contact avec nous sur `le forum `__. + +Conclusion +========== + +Merci de contribuer à Pyromaths ! diff --git a/Doc/source/ecrire/1/exercices.pdf b/Doc/source/ecrire/1/exercices.pdf new file mode 100644 index 00000000..0969f312 Binary files /dev/null and b/Doc/source/ecrire/1/exercices.pdf differ diff --git a/Doc/source/ecrire/1/exercices.tex b/Doc/source/ecrire/1/exercices.tex new file mode 100644 index 00000000..b5e3097e --- /dev/null +++ b/Doc/source/ecrire/1/exercices.tex @@ -0,0 +1,149 @@ +%%!TEX TS-program = latex +\documentclass[a4paper,11pt]{article} +\usepackage[utf8]{inputenc} % UTF-8 +\usepackage[T1]{fontenc} +\usepackage{lmodern} % Prévient un bug d'affichage evince lié à [T1]{fontenc} +\usepackage[frenchb]{babel} % francisation +\usepackage{adjustbox} +\usepackage[fleqn]{amsmath} % aligne le mode maths à gauche +\usepackage{amssymb} % the amsfont symbols +\usepackage[table, usenames, svgnames]{xcolor} % Couleurs +\usepackage{multicol} % Multi-colonnes +\usepackage{fancyhdr} % Mise en page, en-tête et pied de page +\usepackage{calc} % Opérations +\usepackage{marvosym} % Martin Vogels Symbole (\EUR) +\usepackage{cancel} % draw diagonal lines +\usepackage{units} % typesetting units and nice fractions +\usepackage[autolanguage]{numprint} % écrituredes virgules +\usepackage{tabularx} % creates a paragraph-like column whose width +% automatically expands +\usepackage{wrapfig} % allows figures or tables to have text wrapped around +\usepackage{pst-eucl, pst-plot} % figures géométriques +\usepackage{enumitem} +\usepackage{wasysym} % Symbole Euro +\usepackage{mathtools} % Encadrement dans align* +\usepackage[inline]{asymptote} +\usepackage{tkz-tab} +\usetikzlibrary{external} % set up externalization +\tikzexternalize[shell escape=-enable-write18] % activate externalisation +\tikzset{% + external/system call={% + latex \tikzexternalcheckshellescape -halt-on-error + -interaction=batchmode -jobname "\image" "\texsource" && + dvips -o "\image".ps "\image".dvi && + ps2eps -f "\image.ps" + } + } + +%\usepackage{textcomp} + +\usepackage[a4paper, dvips, left=1.5cm, right=1.5cm, top=2cm,% +bottom=2cm, marginpar=5mm, marginparsep=5pt]{geometry} +\newcounter{exo} +\frenchbsetup{StandardItemLabels} % remet \textbullet pour les listes +\setlength{\headheight}{18pt} +\setlength{\fboxsep}{5pt} +\setlength\parindent{0em} +\setlength\mathindent{0em} +\setlength{\columnsep}{30pt} +\usepackage[bookmarks=true, bookmarksnumbered=true, ps2pdf, pagebackref=true,% +colorlinks=true,linkcolor=blue,plainpages=true,unicode]{hyperref} +\hypersetup{pdfauthor={Jérôme Ortais},pdfsubject={Exercices de + mathématiques},pdftitle={Exercices créés par Pyromaths, un logiciel libre + en Python sous licence GPL}} + +\def\pshlabel#1{\psframebox*[fillcolor=White,framearc=.2]{\footnotesize $#1$}} +\def\psvlabel#1{\psframebox*[fillcolor=White,framearc=.2]{\footnotesize $#1$}} + +\makeatletter +\newcommand\styleexo[1][]{ + \renewcommand{\theenumi}{\arabic{enumi}} + \renewcommand{\labelenumi}{$\blacktriangleright$\textbf{\theenumi.}} + \renewcommand{\theenumii}{\alph{enumii}} + \renewcommand{\labelenumii}{\textbf{\theenumii)}} + {\fontfamily{pag}\fontseries{b}\selectfont \underline{#1 \theexo}} + \par\@afterheading\vspace{0.5\baselineskip minus 0.2\baselineskip}} +\newcommand*\exercice{% + \psset{unit=1cm, dash=4pt 4pt, PointName=default,linecolor=Maroon, + dotstyle=x, linestyle=solid, hatchcolor=Peru, gridcolor=Olive, + subgridcolor=Olive, fillcolor=Peru} + %\ifthenelse{\equal{\theexo}{0}}{}{\filbreak} + \refstepcounter{exo}% + \stepcounter{nocalcul}% + \par\addvspace{1.5\baselineskip minus 1\baselineskip}% + \@ifstar% + {\penalty-130\styleexo[Corrigé de l'exercice]}% + {\penalty-130\styleexo[Exercice]}% + } +\newcommand{\checkedbox}[0]{\makebox[0pt][l]{$\square$}\raisebox{.15ex}{\hspace{0pt}$\checkmark$}} +\makeatother +\newlength{\ltxt} +\newsavebox{\mybox} +\newlength{\wdofmybox} +\newcommand{\figureadroite}[2]{% + \setlength{\ltxt}{\linewidth} + \sbox{\mybox}{\hbox{#1}} + \settowidth{\wdofmybox}{\usebox{\mybox}} + \addtolength{\ltxt}{-\wdofmybox} + \addtolength{\ltxt}{-10pt} + \begin{minipage}{\ltxt} + #2 + \end{minipage} + \hfill + \begin{minipage}{\wdofmybox} + #1 + \end{minipage} + } + +\count1=\year \count2=\year +\ifnum\month<8\advance\count1by-1\else\advance\count2by1\fi +\pagestyle{fancy} +\cfoot{\textsl{\footnotesize{Année \number\count1/\number\count2}}} +\rfoot{\textsl{\tiny{http://www.pyromaths.org}}} +\lhead{\textsl{\footnotesize{Page \thepage/ \pageref{LastPage}}}} +\chead{\Large{\textsc{Modèle}}} +\rhead{\textsl{\footnotesize{Modèle}}} + +\begin{document} + \currentpdfbookmark{Les énoncés des exercices}{Énoncés} + \newcounter{nocalcul}[exo] + \renewcommand{\thenocalcul}{\Alph{nocalcul}} + \raggedcolumns + \setlength{\columnseprule}{0.5pt} + + \ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % DÉBUT DE L'ÉNONCÉ + \exercice + + Déterminer les solutions de l'équation $3x+2=-x-1$. Si nécessaire, les solutions seront arrondies au centième. + + % FIN DE L'ÉNONCÉ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + \label{LastPage} + \newpage + \currentpdfbookmark{Le corrigé des exercices}{Corrigé} + \lhead{\textsl{{\footnotesize Page \thepage/ \pageref{LastCorPage}}}} + \setcounter{page}{1} \setcounter{exo}{0} + + \ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % DÉBUT DU CORRIGÉ + \exercice* + + \begin{align*} + 3x+2 &= -x-1 \\ + 3x+x &= -1-2 \\ + 4x &= -3 \\ + x &= -\frac{3}{4} \\ + x &= -0,75 + \end{align*} + + L'unique solution est $x=-0,75$. + + % FIN DU CORRIGÉ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + \label{LastCorPage} +\end{document} diff --git a/Doc/source/ecrire/2/EquationPremierDegre2-answer.tex b/Doc/source/ecrire/2/EquationPremierDegre2-answer.tex new file mode 100644 index 00000000..f7795389 --- /dev/null +++ b/Doc/source/ecrire/2/EquationPremierDegre2-answer.tex @@ -0,0 +1,11 @@ +\exercice* + +\begin{align*} + 3x+2 &= -x-1 \\ + 3x+x &= -1-2 \\ + 4x &= -3 \\ + x &= -\frac{3}{4} \\ + x &= -0,75 +\end{align*} + +L'unique solution est $x=-0,75$. diff --git a/Doc/source/ecrire/2/EquationPremierDegre2-statement.tex b/Doc/source/ecrire/2/EquationPremierDegre2-statement.tex new file mode 100644 index 00000000..540c44a0 --- /dev/null +++ b/Doc/source/ecrire/2/EquationPremierDegre2-statement.tex @@ -0,0 +1,3 @@ +\exercice + +Déterminer les solutions de l'équation $3x+2=-x-1$. Si nécessaire, les solutions seront arrondies au centième. diff --git a/Doc/source/ecrire/2/equation2.py b/Doc/source/ecrire/2/equation2.py new file mode 100644 index 00000000..3a6c9785 --- /dev/null +++ b/Doc/source/ecrire/2/equation2.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# +# Pyromaths +# +# Un programme en Python qui permet de créer des fiches d'exercices types de +# mathématiques niveau collège ainsi que leur corrigé en LaTeX. +# +# Copyright (C) 2018 -- Louis Paternault (spalax+python@gresille.org) +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +"""Équations du premier degré""" + +from pyromaths.ex import Jinja2Exercice + +class EquationPremierDegre2(Jinja2Exercice): + + description = u"Résolution d'équations du premier degré à coefficients entiers." + level = u'3.Troisième' diff --git a/Doc/source/ecrire/2/exercice.pdf b/Doc/source/ecrire/2/exercice.pdf new file mode 100644 index 00000000..e1d5e7ce Binary files /dev/null and b/Doc/source/ecrire/2/exercice.pdf differ diff --git a/Doc/source/ecrire/3/EquationPremierDegre3-answer.tex b/Doc/source/ecrire/3/EquationPremierDegre3-answer.tex new file mode 100644 index 00000000..cbd1becd --- /dev/null +++ b/Doc/source/ecrire/3/EquationPremierDegre3-answer.tex @@ -0,0 +1,11 @@ +\exercice* + +\begin{align*} + (( a )) x (( "%+d"|format(b) )) &= (( c )) x (( "%+d"|format(d) )) \\ + (( a )) x (( "%+d"|format(-c) ))x &= (( d )) (( "%+d"|format(-b) )) \\ + (( a - c )) x &= (( d - b )) \\ + x &= \frac{(( d - b ))}{(( a - c ))} \\ + x &\approx \numprint{(( ((d-b)/(a-c)) | round(2) ))} +\end{align*} + +L'unique solution est $x\approx\numprint{(( ((d-b)/(a-c)) | round(2) ))}$. diff --git a/Doc/source/ecrire/3/EquationPremierDegre3-statement.tex b/Doc/source/ecrire/3/EquationPremierDegre3-statement.tex new file mode 100644 index 00000000..d4d42f7e --- /dev/null +++ b/Doc/source/ecrire/3/EquationPremierDegre3-statement.tex @@ -0,0 +1,4 @@ +\exercice + +Déterminer les solutions de l'équation $(( a )) x (( "%+d"|format(b) ))= (( c )) x (( "%+d"|format(d) ))$. +Si nécessaire, les solutions seront arrondies au centième. diff --git a/Doc/source/ecrire/3/corrige.png b/Doc/source/ecrire/3/corrige.png new file mode 100644 index 00000000..5b4689b2 Binary files /dev/null and b/Doc/source/ecrire/3/corrige.png differ diff --git a/Doc/source/ecrire/3/equation3.py b/Doc/source/ecrire/3/equation3.py new file mode 100644 index 00000000..485f146b --- /dev/null +++ b/Doc/source/ecrire/3/equation3.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# +# Pyromaths +# +# Un programme en Python qui permet de créer des fiches d'exercices types de +# mathématiques niveau collège ainsi que leur corrigé en LaTeX. +# +# Copyright (C) 2018 -- Louis Paternault (spalax+python@gresille.org) +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +"""Équations du premier degré""" + +import random + +from pyromaths.ex import Jinja2Exercice + +class EquationPremierDegre3(Jinja2Exercice): + + description = u"Résolution d'équations du premier degré à coefficients entiers." + level = u'3.Troisième' + + def __init__(self): + super(EquationPremierDegre3, self).__init__() + + self.context = { + "a": random.choice([1, -1]) * random.randint(2, 9), + "b": random.choice([1, -1]) * random.randint(2, 9), + "c": random.choice([1, -1]) * random.randint(2, 9), + "d": random.choice([1, -1]) * random.randint(2, 9), + } diff --git a/Doc/source/ecrire/3/exercice.pdf b/Doc/source/ecrire/3/exercice.pdf new file mode 100644 index 00000000..0b8b3a7c Binary files /dev/null and b/Doc/source/ecrire/3/exercice.pdf differ diff --git a/Doc/source/ecrire/4/EquationPremierDegre4-answer.tex b/Doc/source/ecrire/4/EquationPremierDegre4-answer.tex new file mode 100644 index 00000000..0b692f6c --- /dev/null +++ b/Doc/source/ecrire/4/EquationPremierDegre4-answer.tex @@ -0,0 +1,24 @@ +\exercice* + +\begin{align*} + (( a )) x (( "%+d"|format(b) )) &= (( c )) x (( "%+d"|format(d) )) \\ + (( a )) x (( "%+d"|format(-c) ))x &= (( d )) (( "%+d"|format(-b) )) \\ + (( a - c )) x &= (( d - b )) \\ + x &= \frac{(( d - b ))}{(( a - c ))} \\ + x & + (* if 100*(d-b)/(a-c) == (100*(d-b)/(a-c))|int *) + = + (* else *) + \approx + (* endif *) + \numprint{(( ((d-b)/(a-c)) | round(2) ))} +\end{align*} + +L'unique solution est +$x +(* if 100*(d-b)/(a-c) == (100*(d-b)/(a-c))|int *) + = +(* else *) + \approx +(* endif *) +\numprint{(( ((d-b)/(a-c)) | round(2) ))}$. diff --git a/Doc/source/ecrire/4/EquationPremierDegre4-statement.tex b/Doc/source/ecrire/4/EquationPremierDegre4-statement.tex new file mode 100644 index 00000000..d4d42f7e --- /dev/null +++ b/Doc/source/ecrire/4/EquationPremierDegre4-statement.tex @@ -0,0 +1,4 @@ +\exercice + +Déterminer les solutions de l'équation $(( a )) x (( "%+d"|format(b) ))= (( c )) x (( "%+d"|format(d) ))$. +Si nécessaire, les solutions seront arrondies au centième. diff --git a/Doc/source/ecrire/4/equation4.py b/Doc/source/ecrire/4/equation4.py new file mode 100644 index 00000000..3c6cc24f --- /dev/null +++ b/Doc/source/ecrire/4/equation4.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# +# Pyromaths +# +# Un programme en Python qui permet de créer des fiches d'exercices types de +# mathématiques niveau collège ainsi que leur corrigé en LaTeX. +# +# Copyright (C) 2018 -- Louis Paternault (spalax+python@gresille.org) +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +"""Équations du premier degré""" + +import random + +from pyromaths.ex import Jinja2Exercice + +class EquationPremierDegre4(Jinja2Exercice): + + description = u"Résolution d'équations du premier degré à coefficients entiers." + level = u'3.Troisième' + + def __init__(self): + super(EquationPremierDegre4, self).__init__() + + self.context = { + "a": random.choice([1, -1]) * random.randint(2, 9), + "b": random.choice([1, -1]) * random.randint(2, 9), + "c": random.choice([1, -1]) * random.randint(2, 9), + "d": random.choice([1, -1]) * random.randint(2, 9), + } diff --git a/Doc/source/ecrire/4/exercice.pdf b/Doc/source/ecrire/4/exercice.pdf new file mode 100644 index 00000000..a541a6e7 Binary files /dev/null and b/Doc/source/ecrire/4/exercice.pdf differ diff --git a/Doc/source/ecrire/5/EquationPremierDegre5-answer.tex b/Doc/source/ecrire/5/EquationPremierDegre5-answer.tex new file mode 100644 index 00000000..71a9a679 --- /dev/null +++ b/Doc/source/ecrire/5/EquationPremierDegre5-answer.tex @@ -0,0 +1,24 @@ +\exercice* + +\begin{align*} + (( a )) x (( "%+d"|format(b) )) &= (( c )) x (( "%+d"|format(d) )) \\ + (( a )) x (( "%+d"|format(-c) ))x &= (( d )) (( "%+d"|format(-b) )) \\ + (( a - c )) x &= (( d - b )) \\ + x &= \frac{(( d - b ))}{(( a - c ))} \\ + x & + (* if 100*(d-b)/(a-c) == (100*(d-b)/(a-c))|int *) + = + (* else *) + \approx + (* endif *) + (( ((d-b)/(a-c))|facteur("2") )) +\end{align*} + +L'unique solution est +$x +(* if 100*(d-b)/(a-c) == (100*(d-b)/(a-c))|int *) + = +(* else *) + \approx +(* endif *) +(( ((d-b)/(a-c))|facteur("2") ))$. diff --git a/Doc/source/ecrire/5/EquationPremierDegre5-statement.tex b/Doc/source/ecrire/5/EquationPremierDegre5-statement.tex new file mode 100644 index 00000000..d4d42f7e --- /dev/null +++ b/Doc/source/ecrire/5/EquationPremierDegre5-statement.tex @@ -0,0 +1,4 @@ +\exercice + +Déterminer les solutions de l'équation $(( a )) x (( "%+d"|format(b) ))= (( c )) x (( "%+d"|format(d) ))$. +Si nécessaire, les solutions seront arrondies au centième. diff --git a/Doc/source/ecrire/5/equation5.py b/Doc/source/ecrire/5/equation5.py new file mode 100644 index 00000000..cd81ead4 --- /dev/null +++ b/Doc/source/ecrire/5/equation5.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# +# Pyromaths +# +# Un programme en Python qui permet de créer des fiches d'exercices types de +# mathématiques niveau collège ainsi que leur corrigé en LaTeX. +# +# Copyright (C) 2018 -- Louis Paternault (spalax+python@gresille.org) +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +"""Équations du premier degré""" + +import random + +from pyromaths.ex import Jinja2Exercice +from pyromaths.outils.jinja2 import facteur + +class EquationPremierDegre5(Jinja2Exercice): + + description = u"Résolution d'équations du premier degré à coefficients entiers." + level = u'3.Troisième' + + def __init__(self): + super(EquationPremierDegre5, self).__init__() + + self.context = { + "a": random.choice([1, -1]) * random.randint(2, 9), + "b": random.choice([1, -1]) * random.randint(2, 9), + "c": random.choice([1, -1]) * random.randint(2, 9), + "d": random.choice([1, -1]) * random.randint(2, 9), + } + + @property + def environment(self): + environment = super(EquationPremierDegre5, self).environment + environment.filters.update({ + 'facteur': facteur, + }) + return environment diff --git a/Doc/source/ecrire/5/exercice.pdf b/Doc/source/ecrire/5/exercice.pdf new file mode 100644 index 00000000..cec2e162 Binary files /dev/null and b/Doc/source/ecrire/5/exercice.pdf differ diff --git a/Doc/source/ecrire/6.1/EquationPremierDegre61-answer.tex b/Doc/source/ecrire/6.1/EquationPremierDegre61-answer.tex new file mode 100644 index 00000000..e5bdf2bb --- /dev/null +++ b/Doc/source/ecrire/6.1/EquationPremierDegre61-answer.tex @@ -0,0 +1,7 @@ +\exercice* + +\begin{align*} + (( calculs|join("\n") )) +\end{align*} + +(( conclusion )) diff --git a/Doc/source/ecrire/6.1/EquationPremierDegre61-statement.tex b/Doc/source/ecrire/6.1/EquationPremierDegre61-statement.tex new file mode 100644 index 00000000..d4d42f7e --- /dev/null +++ b/Doc/source/ecrire/6.1/EquationPremierDegre61-statement.tex @@ -0,0 +1,4 @@ +\exercice + +Déterminer les solutions de l'équation $(( a )) x (( "%+d"|format(b) ))= (( c )) x (( "%+d"|format(d) ))$. +Si nécessaire, les solutions seront arrondies au centième. diff --git a/Doc/source/ecrire/6.1/equation61.py b/Doc/source/ecrire/6.1/equation61.py new file mode 100644 index 00000000..5764dbf5 --- /dev/null +++ b/Doc/source/ecrire/6.1/equation61.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +# +# Pyromaths +# +# Un programme en Python qui permet de créer des fiches d'exercices types de +# mathématiques niveau collège ainsi que leur corrigé en LaTeX. +# +# Copyright (C) 2018 -- Louis Paternault (spalax+python@gresille.org) +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +"""Équations du premier degré""" + +import random + +from pyromaths.ex import Jinja2Exercice +from pyromaths.outils.jinja2 import facteur + +class EquationPremierDegre61(Jinja2Exercice): + + description = u"Résolution d'équations du premier degré à coefficients entiers." + level = u'3.Troisième' + + def __init__(self): + super(EquationPremierDegre61, self).__init__() + + a = random.choice([1, -1]) * random.randint(2, 9) + b = random.choice([1, -1]) * random.randint(2, 9) + c = random.choice([1, -1]) * random.randint(2, 9) + d = random.choice([1, -1]) * random.randint(2, 9) + + calculs = [ + r"{a}x{b:+d} &= {c}x{d:+d}\\".format(a=a, b=b, c=c, d=d), + r"{a}x{c:+d}x &= {d}{b:+d}\\".format(a=a, b=-b, c=-c, d=d), + ] + if a-c == 0: + calculs.append(r"0 &= {}\\".format(d-b)) + if d == b: + conclusion = u"Puisque $0=0$ est toujours vrai, alors l'équation a une infinité de solutions : tous les nombres réels sont des solutions." + else: + conclusion = u"Puisque $0={}$ est toujours faux, alors l'équation n'a aucune solution.".format(d-b) + elif a-c == -1: + calculs.append(r"-x &= {}\\".format(d-b)) + calculs.append(r"(-1)\times -x&= (-1)\times {}\\".format(d-b)) + calculs.append(r"x&={}\\".format(b-d)) + conclusion = r"L'unique solution est $x = {}$.".format(b-d) + elif a-c == 1: + calculs.append(r"x &= {}\\".format(d-b)) + conclusion = r"L'unique solution est $x = {}$.".format(d-b) + else: + calculs.append(r"{}x &= {}\\".format(a-c, d-b)) + calculs.append(r"x&=\frac{{ {} }}{{ {} }}\\".format(d-b, a-c)) + solution = facteur(float(d-b)/float(a-c), "2") + if 100*(float(d-b)/float(a-c)) == int(100 * float(d-b)/float(a-c)): + calculs.append(r"x&={}\\".format(solution)) + conclusion = r"L'unique solution est $x = {}$.".format(solution) + else: + calculs.append(r"x&\approx{}\\".format(solution)) + conclusion = r"L'unique solution est $x \approx {}$.".format(solution) + self.context = { + "a": a, + "b": b, + "c": c, + "d": d, + "calculs": calculs, + "conclusion": conclusion, + } diff --git a/Doc/source/ecrire/6.2/EquationPremierDegre62-answer.tex b/Doc/source/ecrire/6.2/EquationPremierDegre62-answer.tex new file mode 100644 index 00000000..34f4a942 --- /dev/null +++ b/Doc/source/ecrire/6.2/EquationPremierDegre62-answer.tex @@ -0,0 +1,41 @@ +\exercice* + +\begin{align*} + (( a )) x (( "%+d"|format(b) )) &= (( c )) x (( "%+d"|format(d) )) \\ + (( a )) x (( "%+d"|format(-c) ))x &= (( d )) (( "%+d"|format(-b) )) \\ + (* if a == c *) + 0 &= (( d - b )) \\ + (* else *) + (* if a - c == 1 *) + % Rien + (* elif a - c == -1 *) + -x &= (( d - b )) \\ + -1 \times -x &= -1 \times (( d - b )) \\ + (* else *) + (( a - c )) x &= (( d - b )) \\ + x &= \frac{(( d - b ))}{(( a - c ))} \\ + (* endif *) + x & + (* if 100*(d-b)/(a-c) == (100*(d-b)/(a-c))|int *) + = + (* else *) + \approx + (* endif *) + (( ((d-b)/(a-c)) | facteur("2") )) + (* endif *) +\end{align*} + +(* if a == c and b == d *) + Puisque $0=0$ est toujours vrai, l'équation a une infinité de solutions : tous les nombres réels. +(* elif a == c and b != d *) + Puisque $0=((d - b))$ est toujours faux, l'équation n'a pas de solutions. +(* else *) + L'unique solution est + $x + (* if 100*(d-b)/(a-c) == (100*(d-b)/(a-c))|int *) + = + (* else *) + \approx + (* endif *) + (( ((d-b)/(a-c)) | facteur("2") ))$. +(* endif *) diff --git a/Doc/source/ecrire/6.2/EquationPremierDegre62-statement.tex b/Doc/source/ecrire/6.2/EquationPremierDegre62-statement.tex new file mode 100644 index 00000000..d4d42f7e --- /dev/null +++ b/Doc/source/ecrire/6.2/EquationPremierDegre62-statement.tex @@ -0,0 +1,4 @@ +\exercice + +Déterminer les solutions de l'équation $(( a )) x (( "%+d"|format(b) ))= (( c )) x (( "%+d"|format(d) ))$. +Si nécessaire, les solutions seront arrondies au centième. diff --git a/Doc/source/ecrire/6.2/equation62.py b/Doc/source/ecrire/6.2/equation62.py new file mode 100644 index 00000000..e84c5804 --- /dev/null +++ b/Doc/source/ecrire/6.2/equation62.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# +# Pyromaths +# +# Un programme en Python qui permet de créer des fiches d'exercices types de +# mathématiques niveau collège ainsi que leur corrigé en LaTeX. +# +# Copyright (C) 2018 -- Louis Paternault (spalax+python@gresille.org) +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +"""Équations du premier degré""" + +import random + +from pyromaths.ex import Jinja2Exercice +from pyromaths.outils.jinja2 import facteur + +class EquationPremierDegre62(Jinja2Exercice): + + description = u"Résolution d'équations du premier degré à coefficients entiers." + level = u'3.Troisième' + + def __init__(self): + super(EquationPremierDegre62, self).__init__() + + self.context = { + "a": random.choice([1, -1]) * random.randint(2, 9), + "b": random.choice([1, -1]) * random.randint(2, 9), + "c": random.choice([1, -1]) * random.randint(2, 9), + "d": random.choice([1, -1]) * random.randint(2, 9), + } + + @property + def environment(self): + environment = super(EquationPremierDegre62, self).environment + environment.filters.update({ + 'facteur': facteur, + }) + return environment diff --git a/Doc/source/ecrire/6.3/EquationPremierDegre63-answer.tex b/Doc/source/ecrire/6.3/EquationPremierDegre63-answer.tex new file mode 100644 index 00000000..4567e22f --- /dev/null +++ b/Doc/source/ecrire/6.3/EquationPremierDegre63-answer.tex @@ -0,0 +1,24 @@ +\exercice* + +\begin{align*} + (( a )) x (( "%+d"|format(b) )) &= (( c )) x (( "%+d"|format(d) )) \\ + (( a )) x (( "%+d"|format(-c) ))x &= (( d )) (( "%+d"|format(-b) )) \\ + (( a - c )) x &= (( d - b )) \\ + x &= \frac{(( d - b ))}{(( a - c ))} \\ + x & + (* if 100*(d-b)/(a-c) == (100*(d-b)/(a-c))|int *) + = + (* else *) + \approx + (* endif *) + (( ((d-b)/(a-c)) | facteur("2") )) +\end{align*} + +L'unique solution est +$x +(* if 100*(d-b)/(a-c) == (100*(d-b)/(a-c))|int *) + = +(* else *) + \approx +(* endif *) +(( ((d-b)/(a-c)) | facteur("2") ))$. diff --git a/Doc/source/ecrire/6.3/EquationPremierDegre63-statement.tex b/Doc/source/ecrire/6.3/EquationPremierDegre63-statement.tex new file mode 100644 index 00000000..d4d42f7e --- /dev/null +++ b/Doc/source/ecrire/6.3/EquationPremierDegre63-statement.tex @@ -0,0 +1,4 @@ +\exercice + +Déterminer les solutions de l'équation $(( a )) x (( "%+d"|format(b) ))= (( c )) x (( "%+d"|format(d) ))$. +Si nécessaire, les solutions seront arrondies au centième. diff --git a/Doc/source/ecrire/6.3/equation63.py b/Doc/source/ecrire/6.3/equation63.py new file mode 100644 index 00000000..c2cbe271 --- /dev/null +++ b/Doc/source/ecrire/6.3/equation63.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# +# Pyromaths +# +# Un programme en Python qui permet de créer des fiches d'exercices types de +# mathématiques niveau collège ainsi que leur corrigé en LaTeX. +# +# Copyright (C) 2018 -- Louis Paternault (spalax+python@gresille.org) +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +"""Équations du premier degré""" + +import random + +from pyromaths.ex import Jinja2Exercice +from pyromaths.outils.jinja2 import facteur + +class EquationPremierDegre63(Jinja2Exercice): + + description = u"Résolution d'équations du premier degré à coefficients entiers." + level = u'3.Troisième' + + def __init__(self): + super(EquationPremierDegre63, self).__init__() + + while True: + a = random.choice([1, -1]) * random.randint(2, 9) + b = random.choice([1, -1]) * random.randint(2, 9) + c = random.choice([1, -1]) * random.randint(2, 9) + d = random.choice([1, -1]) * random.randint(2, 9) + + if abs(a-c) == 1: + # 1x ou -1x sera affiché à un moment ou à un autre. Nous excluons ce cas. + continue + if a == c: + # Aucune solution, ou une infinité de solutions. Nous excluons ce cas. + continue + break + + self.context = { + "a": a, + "b": b, + "c": c, + "d": d, + } + + @property + def environment(self): + environment = super(EquationPremierDegre63, self).environment + environment.filters.update({ + 'facteur': facteur, + }) + return environment diff --git a/Doc/source/ecrire/6/1x.png b/Doc/source/ecrire/6/1x.png new file mode 100644 index 00000000..21edf268 Binary files /dev/null and b/Doc/source/ecrire/6/1x.png differ diff --git a/Doc/source/ecrire/install.sh b/Doc/source/ecrire/install.sh new file mode 100755 index 00000000..dc9d51a3 --- /dev/null +++ b/Doc/source/ecrire/install.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# Installe les exercices de tests pour qu'ils puissent être compilés + +DOCDIR=$(pwd)/$(dirname $0) +ROOT=$DOCDIR/../../.. +TEMPLATEDIR=$ROOT/data/ex/templates +EXERCICEDIR=$ROOT/src/pyromaths/ex/troisiemes + +cd $TEMPLATEDIR +for template in $DOCDIR/*/*tex +do + ln $template +done + +cd $EXERCICEDIR +for exercice in $DOCDIR/*/*py +do + ln $exercice +done diff --git a/Doc/source/index.rst b/Doc/source/index.rst index d1e181d3..b8bd6221 100644 --- a/Doc/source/index.rst +++ b/Doc/source/index.rst @@ -16,6 +16,7 @@ Table des matières :numbered: intro.rst + ecrire pyromaths.api pyromaths.cli diff --git a/Doc/source/pyromaths.cli.rst b/Doc/source/pyromaths.cli.rst index e6510839..773ab7b4 100644 --- a/Doc/source/pyromaths.cli.rst +++ b/Doc/source/pyromaths.cli.rst @@ -1,3 +1,5 @@ +.. _pyromaths-cli: + ============================== Interface en ligne de commande ============================== diff --git a/Doc/source/pyromaths.exemples.rst b/Doc/source/pyromaths.exemples.rst index 8b54255b..2b469fb6 100644 --- a/Doc/source/pyromaths.exemples.rst +++ b/Doc/source/pyromaths.exemples.rst @@ -1064,6 +1064,141 @@ Calculs avec étapes >>> plotify('Polynome([[Fraction(-5, 192), 4], [Fraction(2, 96), 3], [Fraction(41, 48), 2], [Fraction(-7, 12), 1], [-4, 0]], "x", False)') -5/192*x^4+2/96*x^3+41/48*x^2-7/12*x^1-4 +Jinja2 +------ + +:ref:`Ce module ` fournit des outils à utiliser avec les templates `jinja2 `__ (voir le :ref:`tutoriel de création d'exercices ` pour plus d'informations). + +.. currentmodule:: pyromaths.outils.jinja2 + +.. testsetup:: jinja2 + + from pyromaths.outils.jinja2 import * + +* Affichage de facteurs + + + - Cas de base + + .. doctest:: jinja2 + + >>> facteur(2) + '\\numprint{2}' + >>> facteur(2.0) + '\\numprint{2}' + >>> facteur(2.3) + '\\numprint{2.3}' + + - Arrondi + + .. doctest:: jinja2 + + >>> facteur(12345.6789, arrondi=None) + '\\numprint{12345.6789}' + >>> facteur(12345.6789, arrondi=0) + '\\numprint{12346}' + >>> facteur(12345.6789, arrondi=2) + '\\numprint{12345.68}' + >>> facteur(.6789, arrondi=0) + '\\numprint{1}' + >>> facteur(.6789, arrondi=2) + '\\numprint{0.68}' + + - Affichage (ou non) des zéros à la fin du nombre + + .. doctest:: jinja2 + + >>> facteur(12345.6789, arrondi=None, zero=True) + '\\numprint{12345.6789}' + >>> facteur(12345, arrondi=2, zero=True) + '\\numprint{12345.00}' + >>> facteur(12345, arrondi=2, zero=False) + '\\numprint{12345}' + >>> facteur(12345.7, arrondi=2, zero=True) + '\\numprint{12345.70}' + >>> facteur(12345.7, arrondi=2, zero=False) + '\\numprint{12345.7}' + + - Ajout de parenthèses si le nombre est négatif + + .. doctest:: jinja2 + + >>> facteur(-2, parentheses=True) + '\\left(\\numprint{-2}\\right)' + >>> facteur(2, parentheses=True) + '\\numprint{2}' + + - Affichage du signe `+` + + .. doctest:: jinja2 + + >>> facteur(-2, signe=True) + '\\numprint{-2}' + >>> facteur(2, signe=True) + '\\numprint{+2}' + >>> facteur(2, signe=False) + '\\numprint{2}' + + - Si le signe est une opération (et non pas un opérateur unaire, l'afficher à l'extérieur de ``\numprint{}``. + + .. doctest:: jinja2 + + >>> facteur(-2, operation=False) + '\\numprint{-2}' + >>> facteur(2, signe=True, operation=False) + '\\numprint{+2}' + >>> facteur(-2, operation=True) + '-\\numprint{2}' + >>> facteur(2, signe=True, operation=True) + '+\\numprint{2}' + + - Ne pas afficher un produit par 1 ; seulement le signe avec -1 ; ou rien avec 0. + + .. doctest:: jinja2 + + >>> facteur(1, produit=True, variable="x") + '+x' + >>> facteur(-1, produit=True, variable="x") + '-x' + >>> facteur(0, produit=True, variable="x") + '' + + - Variable + + .. doctest:: jinja2 + + >>> facteur(2, variable='x') + '\\numprint{2}x' + >>> facteur(-1, produit=True, variable='x') + '-x' + + - Version courte des arguments + + .. doctest:: jinja2 + + >>> facteur(-2, court="2zXo") + '-\\numprint{2.00}x^2' + >>> facteur(-2, court="2zXp") + '\\left(\\numprint{-2.00}x^2\\right)' + >>> facteur(-2, court="2zY") + '\\numprint{-2.00}y^2' + >>> facteur(-1, court="y*") + '-y' + >>> facteur(1, court="p*x") + 'x' + >>> facteur(-1, court="p*x") + '\\left(-x\\right)' + >>> facteur(-2, court="p*x") + '\\left(\\numprint{-2}x\\right)' + >>> facteur(2, court="p*x") + '\\numprint{2}x' + +* Affichage de matrices + + .. doctest:: jinja2 + >>> matrice([[1, 2], [3, 4]]) + u'\\begin{pmatrix}\\numprint{1} & \\numprint{2}\\\\\\numprint{3} & \\numprint{4}\\\\\\end{pmatrix}' + .. TODO:: Liste des fichiers dans lesquels aller chercher des classes et fonctions à documenter. diff --git a/Doc/source/pyromaths.outils.jinja2.rst b/Doc/source/pyromaths.outils.jinja2.rst new file mode 100644 index 00000000..81f26e68 --- /dev/null +++ b/Doc/source/pyromaths.outils.jinja2.rst @@ -0,0 +1,9 @@ +.. _pyromaths.outils.jinja2: + +:mod:`jinja2` --- Utilitaires à utiliser avec les *templates* jinja2 +==================================================================== + +.. automodule:: pyromaths.outils.jinja2 + :members: + :special-members: + :undoc-members: diff --git a/Doc/source/pyromaths.outils.rst b/Doc/source/pyromaths.outils.rst index d4cbea12..48088b5b 100644 --- a/Doc/source/pyromaths.outils.rst +++ b/Doc/source/pyromaths.outils.rst @@ -7,5 +7,6 @@ Les outils de Pyromaths pyromaths.outils.Affichage.rst pyromaths.outils.Arithmetique.rst pyromaths.outils.Conversions.rst + pyromaths.outils.jinja2.rst pyromaths.outils.Priorites3.rst diff --git a/NEWS b/NEWS index 302c40cc..8c006f59 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,13 @@ +Version 18.06 +* Nouvel exercice niveau terminale ES (spécialité) : Déterminer l'état stable d'un graphe probabiliste (en utilisant un système d'équations). +* Nouvel exercice niveau terminale ES (spécialité) : Résoudre un système d'équations en utilisant les matrices. +* Nouvel exercice niveau seconde : Bilan sur les trinômes. +* Création d'une nouvelle classe d'exercices (rétro-compatible), pour faciliter l'écriture d'exercices en utilisant le moteur de templates jinja2. +* Documentation : Ajout d'une page d'exemples. +* Documentation : Ajout d'un tutoriel pour la création de nouveaux exercices. +* Mise à jour de `cree-vignettes.py` (utilisé pour créer les vignettes des exercices). +* Nettoyage du code ; petites corrections de bug ; améliorations diverses. + Version 18.05 * L'outils `testexo.py` a été renommé en `pyromaths.cli`. * C'est désormais une interface en ligne de commandes à Pyromaths diff --git a/data/ex/img/BilanTrinomeSansDiscriminant.png b/data/ex/img/BilanTrinomeSansDiscriminant.png new file mode 100644 index 00000000..6353bbce Binary files /dev/null and b/data/ex/img/BilanTrinomeSansDiscriminant.png differ diff --git a/data/ex/img/EtatStableSysteme2.png b/data/ex/img/EtatStableSysteme2.png new file mode 100644 index 00000000..15189cc2 Binary files /dev/null and b/data/ex/img/EtatStableSysteme2.png differ diff --git a/data/ex/img/InterpolationMatrices.png b/data/ex/img/InterpolationMatrices.png new file mode 100644 index 00000000..cb648f80 Binary files /dev/null and b/data/ex/img/InterpolationMatrices.png differ diff --git a/data/ex/img/md5sum.json b/data/ex/img/md5sum.json index ab6601f4..3e00a828 100644 --- a/data/ex/img/md5sum.json +++ b/data/ex/img/md5sum.json @@ -1,6 +1,7 @@ { "Arithmetique": "36c89ba9c16cbb81ced232cb1351cf2f", "ArrondirNombreDecimal": "08996c503f0247ecb648384bb7b2e107", + "BilanTrinomeSansDiscriminant": "e657e58f9faf4fd3c7d1ac4aa85ee21a", "CalculMental": "4901e9079081b9e8d7144e68471245f9", "ClasserNombres": "8585b809a4a76662119cc707e07e7ea5", "ConstruireZigZag": "70d954ff1917c2325c7361b48d33d159", @@ -9,8 +10,10 @@ "Droites": "25d39b1644c2ac6eb069c7d01f3bfdca", "EcrireNombreLettre": "fdc2fe3da7b2f17c85fcc7126deb100d", "EcritureFractionnaire": "ef797cc813006127ea3685130d39691c", + "EtatStableSysteme2": "c28bc307317dca72f2c4bad4d1f134ba", "Fd1Tangentes": "10ed3a781b3ee3ee8480ed73db2e90c9", "FractionPartage": "d798dc7ffae542cb6881fd5da25958bb", + "InterpolationMatrices": "2a209226153e27a847a9ecbf3ee7b223", "MesureAngles": "d5422b7c1b3a0820ab656ac4dc5dba8b", "Operations": "e6fa199addd2b8b0805dc02079628521", "Perpendiculaires": "80dc4d19e3f46d4b2e420dfbea25fa05", diff --git a/data/ex/templates/BilanTrinomeSansDiscriminant-answer.tex b/data/ex/templates/BilanTrinomeSansDiscriminant-answer.tex new file mode 100644 index 00000000..337ce265 --- /dev/null +++ b/data/ex/templates/BilanTrinomeSansDiscriminant-answer.tex @@ -0,0 +1,137 @@ +\exercice* + +On considère le trinôme du second degré $f: x\mapsto (( a|facteur("X") )) (( b|facteur("so*x") )) (( c|facteur("so") ))$. + +\begin{enumerate} +\item +\begin{enumerate} + \item Soit $x\in\mathbb{R}$. Alors : + \begin{align*} + (( a|facteur )) \,\left( x (( -x1|facteur("so") )) \right) \, \left( x (( -x2|facteur("so") )) \right) + &= (( a|facteur )) \,\left(x\times x (( -x1|facteur("so") ))\times x (( -x2|facteur("so") ))\times x (( -x1|facteur("so") ))\times (( -x2|facteur("p") )) \right) \\ + &= (( a|facteur )) \,\left(x^2 (( (-x1-x2)|facteur("so*x") )) (( (x1*x2)|facteur("so*") ))\right) \\ + &= (( a|facteur("X") )) (( a|facteur("so") ))\times(( (-x1-x2)|facteur("px") )) (( a|facteur("so") ))\times(( (x1*x2)|facteur("p") )) \\ + &= (( a|facteur("X") )) (( b|facteur("so*x") )) (( c|facteur("so") ))\\ + &= f\,(x) + \end{align*} + \item Soit $x\in\mathbb{R}$. Alors : + \begin{align*} + (( a|facteur ))\,\left( x (( -alpha|facteur("so") )) \right)^2 (( beta|facteur("so") )) + &= (( a|facteur ))\,\left( x^2 (( (-signealpha*2)|facteur("so") ))\times (( absalpha|facteur )) \times x + (( absalpha|facteur ))^2\right) (( beta|facteur("so") ))\\ + &= (( a|facteur ))\,\left( x^2 (( (-alpha*2)|facteur("sox") )) + (( (absalpha**2)|facteur ))\right) (( beta|facteur("so") ))\\ + &= (( a|facteur("X") )) (( a|facteur("so") ))\times (( (-alpha*2)|facteur("px") )) (( a|facteur("so") ))\times (( (absalpha**2)|facteur )) (( beta|facteur("so") ))\\ + &= (( a|facteur("X") )) (( b|facteur("so*x") )) (( (a*absalpha**2)|facteur("so") )) (( beta|facteur("so") ))\\ + &= (( a|facteur("X") )) (( b|facteur("so*x") )) (( c|facteur("so") ))\\ + &= f\,(x) + \end{align*} +\end{enumerate} +\item Résoudre les équations suivantes en choisissant la forme appropriée de $f$. +\begin{enumerate} +\item En prenant la forme factorisée, l'équation $f\,(x)=0$ est équivalente à l'équation produit nul $(( a|facteur ))\,(x (( -x1|facteur("so") )) )\,(x (( -x2|facteur("so") )) ) = 0$. Donc : +\begin{align*} +x (( -x1|facteur("so") ))=0 &\text{ ou } x (( -x2|facteur("so") ))=0 \\ +x=(( x1|facteur )) &\text{ ou } x=(( x2|facteur )) +\end{align*} +Il y a donc deux solutions : $(( x1|facteur ))$ et $(( x2|facteur ))$. +\item $f\,(x)=(( c|facteur ))$ On remarque que la forme développée contient la constante $(( c|facteur ))$ : celles-ci devraient donc s'annuler, pour simplifier notre résolution. +\begin{align*} +f\,(x) &= (( c|facteur )) \\ +(( a|facteur("X") )) (( b|facteur("so*x") )) (( c|facteur("so") )) &= (( c|facteur )) \\ +(( a|facteur("X") )) (( b|facteur("so*x") )) (( c|facteur("so") )) (( -c|facteur("so") )) &= (( c|facteur )) (( -c|facteur("so") )) \\ +(( a|facteur("X") )) (( b|facteur("so*x") )) &= 0 \\ +\end{align*} +Nous pouvons maintenant factoriser le membre de gauche par $x$, ce qui nous donnera une équation produit nul. +\begin{align*} +(( a|facteur("X") )) (( b|facteur("so*x") )) &= 0 \\ +(( a|facteur("x") ))\times x (( b|facteur("so") ))\times x &= 0 \\ +x\,\left( (( a|facteur("x") )) (( b|facteur("so") )) \right) &= 0 \\ +\end{align*} +\begin{align*} +x =0 &\text{ ou } (( a|facteur("x") )) (( b|facteur("so") ))=0 \\ +x =0 &\text{ ou } (( a|facteur("x") )) =(( -b|facteur )) \\ +x =0 &\text{ ou } x = \frac{(( -b|facteur ))}{(( a|facteur ))} \\ +x =0 &\text{ ou } x = (( -(b/a)|facteur )) \\ +\end{align*} +Il y a donc deux solutions : $x=0$ et $x=(( -(b/a)|facteur ))$. +\item $f\,(x)=(( beta|facteur ))$ On remarque que la forme canonique contient la constante $(( beta|facteur ))$ : en l'utilisant, elles devraient se simplifier. +\begin{align*} +f\,(x) &= (( beta|facteur)) \\ +(( a|facteur )) \,\left( x (( -alpha|facteur("so") )) \right)^2 (( beta|facteur("so") )) &= (( beta|facteur ))\\ +(( a|facteur )) \,\left( x (( -alpha|facteur("so") )) \right)^2 (( beta|facteur("so") )) (( -beta|facteur("so") )) &= (( beta|facteur )) (( -beta|facteur("so") ))\\ +(( a|facteur )) \,\left( x (( -alpha|facteur("so") )) \right)^2 &= 0\\ +\left( x (( -alpha|facteur("so") )) \right)^2 &= 0\\ +\end{align*} +Or $0$ est le seul nombre dont le carré est nul, donc l'équation précédente est équivalente à : +\begin{align*} +x (( -alpha|facteur("so") )) &= 0\\ +x &= (( alpha|facteur )) \\ +\end{align*} +Il y a donc une unique solution $x=(( alpha|facteur ))$. +\end{enumerate} +\item +\begin{enumerate} +\item \emph{Dresser le tableau de variations de $f$.} Dans la forme développée, le coefficient devant le $x^2$ est +(* if a > 0 *) positif (* else *) négatif (* endif *), +donc la fonction est +(* if a > 0 *) décroissante puis croissante (* else *) croissante puis décroissante (* endif *). +De plus, l'absisse du sommet est $-\frac{(( b|facteur ))}{2\times(( a|facteur("p") ))}$, soit $(( alpha|facteur ))$, et +$f\,( (( alpha|facteur )) )=(( a|facteur ))\times(( alpha|facteur("p") ))^2 (( b|facteur("so") ))\times (( alpha|facteur("p") )) (( c|facteur("so") ))=(( beta|facteur ))$. +Le tableau de variations est donc : +\begin{center} + \begin{tikzpicture} + \tkzTabInit[espcl=2.5] + {$x$/1, $f\,(x)$/1.5} + {$-\infty$, $(( alpha|facteur ))$, $+\infty$} + (* if a > 0 *) + \tkzTabVar{+/, -/$(( beta|facteur ))$/, +/} + (* else *) + \tkzTabVar{-/, +/$(( beta|facteur ))$/, -/} + (* endif *) + \end{tikzpicture} +\end{center} +\item \emph{Dresser le tableau de signes de $f$.} Construisons un tableau de signes en utilisant la forme factorisée $f\,(x)=(( a|facteur )) \,\left(x (( -x1|facteur("so") ))\right) \, \left(x (( -x2|facteur("so") ))\right)$. + +\begin{itemize} +\item Le premier facteur $x (( -x1|facteur("so") ))$ est une fonction affine, de coefficient directeur $a=1$ positif, et d'ordonnée à l'origine $b=(( -x1|facteur ))$. Elle est donc négative, puis positive, et change de signe en $-\frac{b}{a}=-\frac{(( -x1|facteur ))}{1}=(( x1|facteur ))$. +\item Le second facteur $x (( -x2|facteur("so") ))$ est aussi une fonction affine, de coefficient directeur $a=1$ positif, et d'ordonnée à l'origine $b=(( -x2|facteur ))$. Elle est donc négative, puis positive, et change de signe en $-\frac{b}{a}=-\frac{(( -x2|facteur ))}{1}=(( x2|facteur ))$. +\end{itemize} +\begin{center} + \begin{tikzpicture} + \tkzTabInit[lgt=4, espcl=2.5] + { + $x$/1, + $(( a|facteur ))$/1, + $x (( -x1|facteur("so") ))$/1, + $x (( -x2|facteur("so") ))$/1, + $f\,(x)=(( a|facteur ))\,\left( x (( -x1|facteur("so") )) \right)\,\left( x (( -x2|facteur("so") )) \right)$/1.5 + } + {$-\infty$, $(( (x1, x2)|min|facteur ))$, $(( (x1, x2)|max|facteur ))$, $+\infty$} + \tkzTabLine{, (( a|signe )), t, (( a|signe )), t, (( a|signe ))} + (* if x1 < x2 *) + \tkzTabLine{, -, z, +, t, +} + \tkzTabLine{, -, t, -, z, +} + (* else *) + \tkzTabLine{, -, t, -, z, +} + \tkzTabLine{, -, z, +, t, +} + (* endif *) + \tkzTabLine{, (( a|signe )), z, (( -a|signe )), z, (( a|signe ))} + \end{tikzpicture} +\end{center} +\end{enumerate} +\item Répondre aux questions suivantes en utilisant le tableau de signes ou de variations. +\begin{enumerate} +\item \emph{Résoudre $f\,(x)\geqslant0$.} En regardant la dernière ligne du tableau de signes, on observe que $f$ est positive sur +(* if a > 0 *) les premier et dernier intervalles (* else *) l'intervalle central (* endif *). +Les solutions sont donc : +(* if a > 0 *) + \[ x\in\interval[open left, scaled]{-\infty}{(( (x1, x2)|min|facteur ))} \cup \interval[open right, scaled]{(( (x1, x2)|max|facteur ))}{+\infty} \] +(* else *) + \[ x\in\interval[scaled]{(( (x1, x2)|min|facteur ))}{(( (x1, x2)|max|facteur ))} \] +(* endif *) +\item \emph{Quel est l'extremum de $f$ ? Est-ce un maximum ou un minimum ? Pour quelle valeur de $x$ est-il atteint ?} On lit sur le tableau de variations que la plus +(* if a > 0 *) petite (* else *) grande (* endif *) +valeur prise par $f$ est $(( beta|facteur ))$. Le +(* if a > 0 *) minimum (* else *) maximum (* endif *) +de $f$ est donc $(( beta|facteur ))$, et il est atteint pour $x=(( alpha|facteur ))$. +\end{enumerate} +\end{enumerate} diff --git a/data/ex/templates/BilanTrinomeSansDiscriminant-statement.tex b/data/ex/templates/BilanTrinomeSansDiscriminant-statement.tex new file mode 100644 index 00000000..bde9bfe4 --- /dev/null +++ b/data/ex/templates/BilanTrinomeSansDiscriminant-statement.tex @@ -0,0 +1,26 @@ +\exercice +On considère le trinôme du second degré $f: x\mapsto (( a|facteur("X") )) (( b|facteur("*sox") )) (( c|facteur("so") ))$. + +\begin{enumerate} +\item +\begin{enumerate} + \item Montrer que pour tout $x\in\mathbb{R}$, on a : $f\,(x)=(( a|facteur )) \,\left( x (( -x1|facteur("so") )) \right) \, \left( x (( -x2|facteur("so") )) \right) $. + \item Montrer que pour tout $x\in\mathbb{R}$, on a : $f\,(x)=(( a|facteur )) \,\left( x (( -alpha|facteur("so") )) \right)^2 (( beta|facteur("so") ))$. +\end{enumerate} +\item Résoudre les équations suivantes en choisissant la forme appropriée de $f$. +\begin{enumerate} +\item $f\,(x)=0$ +\item $f\,(x)=(( c|facteur ))$ +\item $f\,(x)=(( beta|facteur ))$ +\end{enumerate} +\item +\begin{enumerate} +\item Dresser le tableau de variations de $f$. +\item Dresser le tableau de signes de $f$. +\end{enumerate} +\item Répondre aux questions suivantes en utilisant le tableau de signes ou de variations. +\begin{enumerate} +\item Résoudre $f(x)\geqslant0$. +\item Quel est l'extremum de $f$ ? Est-ce un maximum ou un minimum ? Pour quelle valeur de $x$ est-il atteint ? +\end{enumerate} +\end{enumerate} diff --git a/data/ex/templates/EtatStableSysteme2-answer.tex b/data/ex/templates/EtatStableSysteme2-answer.tex new file mode 100644 index 00000000..9f16e33f --- /dev/null +++ b/data/ex/templates/EtatStableSysteme2-answer.tex @@ -0,0 +1,34 @@ +\exercice* +Puisque $P$ est l'état stable, alors $P=P\times M$. + +\begin{align*} + P\times M &= \begin{pmatrix}x&y\end{pmatrix}\times +\begin{pmatrix} + (( a|facteur )) & (( (1-a)|facteur )) \\ + (( (1-b)|facteur )) & (( b|facteur )) \\ +\end{pmatrix}\\ +&= \begin{pmatrix} + (( a|facteur("x") )) + (( (1-b)|facteur("y") )) & (( (1-a)|facteur("x") )) + (( b|facteur("y") )) +\end{pmatrix} +\end{align*} + +Or $\begin{pmatrix}x&y\end{pmatrix}=P=P\times M$, donc les coefficients des matrices sont deux à deux égaux, donc $x=(( a|facteur("x") )) + (( (1-b)|facteur("y") ))$. + +D'autre part, puisque $P$ est un état probabiliste, alors $x+y=1$, donc $y=1-x$. Donc, en remplaçant $y$ par $1-x$ dans l'équation précédente, on obtient : + +\begin{align*} + x &= (( a|facteur("x") )) + (( (1-b)|facteur ))\,(1-x) \\ + x &= (( a|facteur("x") )) + (( (1-b)|facteur )) - (( (1-b)|facteur("x") ))\\ + x-(( a|facteur("x") )) +(( (1-b)|facteur("x") )) &= (( (1-b)|facteur ))\\ + (1-(( a|facteur ))+(( (1-b)|facteur ))) \,x &= (( (1-b)|facteur ))\\ + (( (2-a-b)|facteur("x") )) &= (( (1-b)|facteur ))\\ + x &= \frac{(( (1-b)|facteur ))}{(( (2-a-b)|facteur ))}\\ +x &= (( ((1-b)/(2-a-b))|facteur )) +\end{align*} + +Enfin, puisque $y=1-x$, alors $y=1-(( ((1-b)/(2-a-b))|facteur ))=(( ((1-a)/(2-a-b))|facteur ))$. + +L'unique état stable de ce graphe est donc $\begin{pmatrix} +(( ((1-b)/(2-a-b))|facteur )) & +(( ((1-a)/(2-a-b))|facteur )) +\end{pmatrix}$. diff --git a/data/ex/templates/EtatStableSysteme2-statement.tex b/data/ex/templates/EtatStableSysteme2-statement.tex new file mode 100644 index 00000000..bbc64cb5 --- /dev/null +++ b/data/ex/templates/EtatStableSysteme2-statement.tex @@ -0,0 +1,11 @@ +\exercice +On considère un graphe probabiliste d'ordre 2, dont la matrice de transition est : + +\[ +M=\begin{pmatrix} + (( a|facteur )) & (( (1-a)|facteur )) \\ + (( (1-b)|facteur )) & (( b|facteur )) \\ +\end{pmatrix} +\] + +On note $P=\begin{pmatrix}x&y\end{pmatrix}$ l'état stable de ce graphe. Déterminer $x$ et $y$. diff --git a/data/ex/templates/InterpolationMatrices-answer.tex b/data/ex/templates/InterpolationMatrices-answer.tex new file mode 100644 index 00000000..24e07f34 --- /dev/null +++ b/data/ex/templates/InterpolationMatrices-answer.tex @@ -0,0 +1,64 @@ +\exercice* +\begin{enumerate} + + \item + \begin{enumerate} + \item + \begin{itemize} + \item Puisque $A\,( (( X[0]|facteur ))~;~(( Y[0]|facteur )) )$ est sur la courbe de $f$, alors $f\,( (( X[0]|facteur )) )=(( Y[0]|facteur ))$, soit + $a \times (( X[0]|facteur ))^2+b\times (( X[0]|facteur ))+c=(( Y[0]|facteur ))$, + c'est-à-dire $(( (X[0]**2)|facteur(variable="a") )) + (( X[0]|facteur(variable="b") )) + c = (( Y[0]|facteur ))$. + \item De même, puisque $B\,( (( X[1]|facteur ))~;~(( Y[1]|facteur )) )$ est sur la courbe de $f$, alors $f\,( (( X[1]|facteur )) )=(( Y[1]|facteur ))$, soit + $a \times (( X[1]|facteur ))^2+b\times (( X[1]|facteur ))+c=(( Y[1]|facteur ))$, + c'est-à-dire $(( (X[1]**2)|facteur(variable="a") )) + (( X[1]|facteur(variable="b") )) + c = (( Y[1]|facteur ))$. + \item Enfin, puisque $C\,( (( X[2]|facteur ))~;~(( Y[2]|facteur )) )$ est sur la courbe de $f$, alors $f\,( (( X[2]|facteur )) )=(( Y[2]|facteur ))$, soit + $a \times (( X[2]|facteur ))^2+b\times (( X[2]|facteur ))+c=(( Y[2]|facteur ))$, + c'est-à-dire $(( (X[2]**2)|facteur(variable="a") )) + (( X[2]|facteur(variable="b") )) + c = (( Y[2]|facteur ))$. + \end{itemize} + + On en déduit le système suivant : + \[ \left\{\begin{array}{rcl} + (( (X[0]**2)|facteur(variable="a") )) + (( X[0]|facteur(variable="b") )) + c &=& (( Y[0]|facteur )) \\ + (( (X[1]**2)|facteur(variable="a") )) + (( X[1]|facteur(variable="b") )) + c &=& (( Y[1]|facteur )) \\ + (( (X[2]**2)|facteur(variable="a") )) + (( X[2]|facteur(variable="b") )) + c &=& (( Y[2]|facteur )) \\ + \end{array}\right.\] + \item + +\begin{align*} + \left\{\begin{array}{rcl} + (( (X[0]**2)|facteur(variable="a") )) + (( X[0]|facteur(variable="b") )) + c &=& (( Y[0]|facteur )) \\ + (( (X[1]**2)|facteur(variable="a") )) + (( X[1]|facteur(variable="b") )) + c &=& (( Y[1]|facteur )) \\ + (( (X[2]**2)|facteur(variable="a") )) + (( X[2]|facteur(variable="b") )) + c &=& (( Y[2]|facteur )) \\ + \end{array}\right. +&\iff +\begin{pmatrix} +(( (X[0]**2)|facteur(variable="a") )) + (( X[0]|facteur(variable="b") )) + c \\ +(( (X[1]**2)|facteur(variable="a") )) + (( X[1]|facteur(variable="b") )) + c \\ +(( (X[2]**2)|facteur(variable="a") )) + (( X[2]|facteur(variable="b") )) + c \\ +\end{pmatrix} = (( Y|zip|matrice ))\\ +&\iff +(( M|matrice)) \times (( [["a"], ["b"], ["c"]]|matrice )) = (( Y|zip|matrice )) \\ +&\iff M\, X=R +\end{align*} + + Avec : $M= (( M|matrice ))$, $X= (( [["a"], ["b"], ["c"]]|matrice ))$ et $R= (( Y|zip|matrice ))$. + \end{enumerate} + \item + Comme $M$ est inversible, et que $M\,X = R$, alors $X = M^{-1}\times R$. + + À la calculatrice, on obtient + $M^{-1}\times R=(( M|matrice ))^{-1}\times ((Y|zip|matrice)) = (( A|zip|matrice ))$. + + Ainsi, $a=(( A[0]|facteur ))$, $b=(( A[1]|facteur ))$, et $c=(( A[2]|facteur ))$. + \item +En utilisant les valeurs de $a$, $b$, et $c$ calculées précédemment, nous connaissons l'expression de la fonction : $f\,(x) = (( A[0]|facteur("X") )) (( A[1]|facteur("sox*"))) (( A[2]|facteur("so") ))$. + +Nous pouvons maintenant calculer l'image de $(( x|facteur ))$ par cette fonction : +\begin{align*} +f\,( (( x|facteur )) ) +&= (( A[0]|facteur )) \times (( x|facteur ))^2 (( A[1]|facteur("so") )) \times (( x|facteur)) (( A[2]|facteur("so") ))\\ +&= (( (A[0]*x**2+A[1]*x+A[2])|facteur )) +\end{align*} +Donc $f\,( (( x|facteur )) ) = (( (A[0]*x**2+A[1]*x+A[2])|facteur ))$. +\end{enumerate} + diff --git a/data/ex/templates/InterpolationMatrices-statement.tex b/data/ex/templates/InterpolationMatrices-statement.tex new file mode 100644 index 00000000..408d6465 --- /dev/null +++ b/data/ex/templates/InterpolationMatrices-statement.tex @@ -0,0 +1,25 @@ +\exercice +Dans un repère orthonormé, on cherche à déterminer l'équation d'une fonction dont la courbe passe par les points +$A\,( (( X[0]|facteur )) ~;~ (( Y[0]|facteur )) )$, +$B\,( (( X[1]|facteur )) ~;~ (( Y[1]|facteur )) )$ et +$C\,( (( X[2]|facteur )) ~;~ (( Y[2]|facteur )) )$. + +On cherche un trinôme du second degré, c'est-à-dire une fonction $f$ définie sur $\interval[open]{-\infty}{+\infty}$ par + \mbox{$f\,(x) = a\,x^2 + b\,x + c$} où $a$, $b$ et $c$ sont trois nombres réels, que l'on cherche à déterminer. + + \begin{enumerate} + \item + \begin{enumerate} + \item À partir des données de l'énoncé, écrire un système d'équations traduisant cette situation. + \item En déduire que le système précédent est équivalent à : $M\,X = R$ avec + + $M = (( M|matrice ))$, $X= (( [["a"], ["b"], ["c"]]|matrice ))$ et $R$ une matrice colonne que l'on précisera. + \end{enumerate} + \end{enumerate} + \begin{enumerate} + \setcounter{enumi}{1} + \item On admet que la matrice $M$ est inversible. + Déterminer les valeurs des cœfficients $a$, $b$ et $c$, en détaillant les calculs. + \item Quelle est la valeur de $f\,( (( x|facteur )) )$ ? + + \end{enumerate} diff --git a/data/ex/tests/BilanTrinomeSansDiscriminant.0.answer b/data/ex/tests/BilanTrinomeSansDiscriminant.0.answer new file mode 100644 index 00000000..844e16fb --- /dev/null +++ b/data/ex/tests/BilanTrinomeSansDiscriminant.0.answer @@ -0,0 +1,122 @@ +\exercice* + +On considère le trinôme du second degré $f: x\mapsto \numprint{2}\,x^2 -\numprint{4}\,x -\numprint{70}$. + +\begin{enumerate} +\item +\begin{enumerate} + \item Soit $x\in\mathbb{R}$. Alors : + \begin{align*} + \numprint{2} \,\left( x +\numprint{5} \right) \, \left( x -\numprint{7} \right) + &= \numprint{2} \,\left(x\times x +\numprint{5}\times x -\numprint{7}\times x +\numprint{5}\times \left(\numprint{-7}\right) \right) \\ + &= \numprint{2} \,\left(x^2 -\numprint{2}\,x -\numprint{35}\right) \\ + &= \numprint{2}\,x^2 +\numprint{2}\times\left(\numprint{-2}\,x\right) +\numprint{2}\times\left(\numprint{-35}\right) \\ + &= \numprint{2}\,x^2 -\numprint{4}\,x -\numprint{70}\\ + &= f\,(x) + \end{align*} + \item Soit $x\in\mathbb{R}$. Alors : + \begin{align*} + \numprint{2}\,\left( x -\numprint{1} \right)^2 -\numprint{72} + &= \numprint{2}\,\left( x^2 -\numprint{2}\times \numprint{1} \times x + \numprint{1}^2\right) -\numprint{72}\\ + &= \numprint{2}\,\left( x^2 -\numprint{2}\,x + \numprint{1}\right) -\numprint{72}\\ + &= \numprint{2}\,x^2 +\numprint{2}\times \left(\numprint{-2}\,x\right) +\numprint{2}\times \numprint{1} -\numprint{72}\\ + &= \numprint{2}\,x^2 -\numprint{4}\,x +\numprint{2} -\numprint{72}\\ + &= \numprint{2}\,x^2 -\numprint{4}\,x -\numprint{70}\\ + &= f\,(x) + \end{align*} +\end{enumerate} +\item Résoudre les équations suivantes en choisissant la forme appropriée de $f$. +\begin{enumerate} +\item En prenant la forme factorisée, l'équation $f\,(x)=0$ est équivalente à l'équation produit nul $\numprint{2}\,(x +\numprint{5} )\,(x -\numprint{7} ) = 0$. Donc : +\begin{align*} +x +\numprint{5}=0 &\text{ ou } x -\numprint{7}=0 \\ +x=\numprint{-5} &\text{ ou } x=\numprint{7} +\end{align*} +Il y a donc deux solutions : $\numprint{-5}$ et $\numprint{7}$. +\item $f\,(x)=\numprint{-70}$ On remarque que la forme développée contient la constante $\numprint{-70}$ : celles-ci devraient donc s'annuler, pour simplifier notre résolution. +\begin{align*} +f\,(x) &= \numprint{-70} \\ +\numprint{2}\,x^2 -\numprint{4}\,x -\numprint{70} &= \numprint{-70} \\ +\numprint{2}\,x^2 -\numprint{4}\,x -\numprint{70} +\numprint{70} &= \numprint{-70} +\numprint{70} \\ +\numprint{2}\,x^2 -\numprint{4}\,x &= 0 \\ +\end{align*} +Nous pouvons maintenant factoriser le membre de gauche par $x$, ce qui nous donnera une équation produit nul. +\begin{align*} +\numprint{2}\,x^2 -\numprint{4}\,x &= 0 \\ +\numprint{2}\,x\times x -\numprint{4}\times x &= 0 \\ +x\,\left( \numprint{2}\,x -\numprint{4} \right) &= 0 \\ +\end{align*} +\begin{align*} +x =0 &\text{ ou } \numprint{2}\,x -\numprint{4}=0 \\ +x =0 &\text{ ou } \numprint{2}\,x =\numprint{4} \\ +x =0 &\text{ ou } x = \frac{\numprint{4}}{\numprint{2}} \\ +x =0 &\text{ ou } x = \numprint{2} \\ +\end{align*} +Il y a donc deux solutions : $x=0$ et $x=\numprint{2}$. +\item $f\,(x)=\numprint{-72}$ On remarque que la forme canonique contient la constante $\numprint{-72}$ : en l'utilisant, elles devraient se simplifier. +\begin{align*} +f\,(x) &= \numprint{-72} \\ +\numprint{2} \,\left( x -\numprint{1} \right)^2 -\numprint{72} &= \numprint{-72}\\ +\numprint{2} \,\left( x -\numprint{1} \right)^2 -\numprint{72} +\numprint{72} &= \numprint{-72} +\numprint{72}\\ +\numprint{2} \,\left( x -\numprint{1} \right)^2 &= 0\\ +\left( x -\numprint{1} \right)^2 &= 0\\ +\end{align*} +Or $0$ est le seul nombre dont le carré est nul, donc l'équation précédente est équivalente à : +\begin{align*} +x -\numprint{1} &= 0\\ +x &= \numprint{1} \\ +\end{align*} +Il y a donc une unique solution $x=\numprint{1}$. +\end{enumerate} +\item +\begin{enumerate} +\item \emph{Dresser le tableau de variations de $f$.} Dans la forme développée, le coefficient devant le $x^2$ est + positif , +donc la fonction est + décroissante puis croissante . +De plus, l'absisse du sommet est $-\frac{\numprint{-4}}{2\times\numprint{2}}$, soit $\numprint{1}$, et +$f\,( \numprint{1} )=\numprint{2}\times\numprint{1}^2 -\numprint{4}\times \numprint{1} -\numprint{70}=\numprint{-72}$. +Le tableau de variations est donc : +\begin{center} + \begin{tikzpicture} + \tkzTabInit[espcl=2.5] + {$x$/1, $f\,(x)$/1.5} + {$-\infty$, $\numprint{1}$, $+\infty$} + \tkzTabVar{+/, -/$\numprint{-72}$/, +/} + \end{tikzpicture} +\end{center} +\item \emph{Dresser le tableau de signes de $f$.} Construisons un tableau de signes en utilisant la forme factorisée $f\,(x)=\numprint{2} \,\left(x +\numprint{5}\right) \, \left(x -\numprint{7}\right)$. + +\begin{itemize} +\item Le premier facteur $x +\numprint{5}$ est une fonction affine, de coefficient directeur $a=1$ positif, et d'ordonnée à l'origine $b=\numprint{5}$. Elle est donc négative, puis positive, et change de signe en $-\frac{b}{a}=-\frac{\numprint{5}}{1}=\numprint{-5}$. +\item Le second facteur $x -\numprint{7}$ est aussi une fonction affine, de coefficient directeur $a=1$ positif, et d'ordonnée à l'origine $b=\numprint{-7}$. Elle est donc négative, puis positive, et change de signe en $-\frac{b}{a}=-\frac{\numprint{-7}}{1}=\numprint{7}$. +\end{itemize} +\begin{center} + \begin{tikzpicture} + \tkzTabInit[lgt=4, espcl=2.5] + { + $x$/1, + $\numprint{2}$/1, + $x +\numprint{5}$/1, + $x -\numprint{7}$/1, + $f\,(x)=\numprint{2}\,\left( x +\numprint{5} \right)\,\left( x -\numprint{7} \right)$/1.5 + } + {$-\infty$, $\numprint{-5}$, $\numprint{7}$, $+\infty$} + \tkzTabLine{, +, t, +, t, +} + \tkzTabLine{, -, z, +, t, +} + \tkzTabLine{, -, t, -, z, +} + \tkzTabLine{, +, z, -, z, +} + \end{tikzpicture} +\end{center} +\end{enumerate} +\item Répondre aux questions suivantes en utilisant le tableau de signes ou de variations. +\begin{enumerate} +\item \emph{Résoudre $f\,(x)\geqslant0$.} En regardant la dernière ligne du tableau de signes, on observe que $f$ est positive sur + les premier et dernier intervalles . +Les solutions sont donc : + \[ x\in\interval[open left, scaled]{-\infty}{\numprint{-5}} \cup \interval[open right, scaled]{\numprint{7}}{+\infty} \] +\item \emph{Quel est l'extremum de $f$ ? Est-ce un maximum ou un minimum ? Pour quelle valeur de $x$ est-il atteint ?} On lit sur le tableau de variations que la plus + petite valeur prise par $f$ est $\numprint{-72}$. Le + minimum de $f$ est donc $\numprint{-72}$, et il est atteint pour $x=\numprint{1}$. +\end{enumerate} +\end{enumerate} \ No newline at end of file diff --git a/data/ex/tests/BilanTrinomeSansDiscriminant.0.statement b/data/ex/tests/BilanTrinomeSansDiscriminant.0.statement new file mode 100644 index 00000000..c2be40ab --- /dev/null +++ b/data/ex/tests/BilanTrinomeSansDiscriminant.0.statement @@ -0,0 +1,26 @@ +\exercice +On considère le trinôme du second degré $f: x\mapsto \numprint{2}\,x^2 -\numprint{4}\,x -\numprint{70}$. + +\begin{enumerate} +\item +\begin{enumerate} + \item Montrer que pour tout $x\in\mathbb{R}$, on a : $f\,(x)=\numprint{2} \,\left( x +\numprint{5} \right) \, \left( x -\numprint{7} \right) $. + \item Montrer que pour tout $x\in\mathbb{R}$, on a : $f\,(x)=\numprint{2} \,\left( x -\numprint{1} \right)^2 -\numprint{72}$. +\end{enumerate} +\item Résoudre les équations suivantes en choisissant la forme appropriée de $f$. +\begin{enumerate} +\item $f\,(x)=0$ +\item $f\,(x)=\numprint{-70}$ +\item $f\,(x)=\numprint{-72}$ +\end{enumerate} +\item +\begin{enumerate} +\item Dresser le tableau de variations de $f$. +\item Dresser le tableau de signes de $f$. +\end{enumerate} +\item Répondre aux questions suivantes en utilisant le tableau de signes ou de variations. +\begin{enumerate} +\item Résoudre $f(x)\geqslant0$. +\item Quel est l'extremum de $f$ ? Est-ce un maximum ou un minimum ? Pour quelle valeur de $x$ est-il atteint ? +\end{enumerate} +\end{enumerate} \ No newline at end of file diff --git a/data/ex/tests/BilanTrinomeSansDiscriminant.1.answer b/data/ex/tests/BilanTrinomeSansDiscriminant.1.answer new file mode 100644 index 00000000..6f58af77 --- /dev/null +++ b/data/ex/tests/BilanTrinomeSansDiscriminant.1.answer @@ -0,0 +1,122 @@ +\exercice* + +On considère le trinôme du second degré $f: x\mapsto \numprint{-2}\,x^2 -\numprint{6}\,x +\numprint{80}$. + +\begin{enumerate} +\item +\begin{enumerate} + \item Soit $x\in\mathbb{R}$. Alors : + \begin{align*} + \numprint{-2} \,\left( x -\numprint{5} \right) \, \left( x +\numprint{8} \right) + &= \numprint{-2} \,\left(x\times x -\numprint{5}\times x +\numprint{8}\times x -\numprint{5}\times \numprint{8} \right) \\ + &= \numprint{-2} \,\left(x^2 +\numprint{3}\,x -\numprint{40}\right) \\ + &= \numprint{-2}\,x^2 -\numprint{2}\times\numprint{3}\,x -\numprint{2}\times\left(\numprint{-40}\right) \\ + &= \numprint{-2}\,x^2 -\numprint{6}\,x +\numprint{80}\\ + &= f\,(x) + \end{align*} + \item Soit $x\in\mathbb{R}$. Alors : + \begin{align*} + \numprint{-2}\,\left( x +\numprint{1.5} \right)^2 +\numprint{84.5} + &= \numprint{-2}\,\left( x^2 +\numprint{2}\times \numprint{1.5} \times x + \numprint{1.5}^2\right) +\numprint{84.5}\\ + &= \numprint{-2}\,\left( x^2 +\numprint{3}\,x + \numprint{2.25}\right) +\numprint{84.5}\\ + &= \numprint{-2}\,x^2 -\numprint{2}\times \numprint{3}\,x -\numprint{2}\times \numprint{2.25} +\numprint{84.5}\\ + &= \numprint{-2}\,x^2 -\numprint{6}\,x -\numprint{4.5} +\numprint{84.5}\\ + &= \numprint{-2}\,x^2 -\numprint{6}\,x +\numprint{80}\\ + &= f\,(x) + \end{align*} +\end{enumerate} +\item Résoudre les équations suivantes en choisissant la forme appropriée de $f$. +\begin{enumerate} +\item En prenant la forme factorisée, l'équation $f\,(x)=0$ est équivalente à l'équation produit nul $\numprint{-2}\,(x -\numprint{5} )\,(x +\numprint{8} ) = 0$. Donc : +\begin{align*} +x -\numprint{5}=0 &\text{ ou } x +\numprint{8}=0 \\ +x=\numprint{5} &\text{ ou } x=\numprint{-8} +\end{align*} +Il y a donc deux solutions : $\numprint{5}$ et $\numprint{-8}$. +\item $f\,(x)=\numprint{80}$ On remarque que la forme développée contient la constante $\numprint{80}$ : celles-ci devraient donc s'annuler, pour simplifier notre résolution. +\begin{align*} +f\,(x) &= \numprint{80} \\ +\numprint{-2}\,x^2 -\numprint{6}\,x +\numprint{80} &= \numprint{80} \\ +\numprint{-2}\,x^2 -\numprint{6}\,x +\numprint{80} -\numprint{80} &= \numprint{80} -\numprint{80} \\ +\numprint{-2}\,x^2 -\numprint{6}\,x &= 0 \\ +\end{align*} +Nous pouvons maintenant factoriser le membre de gauche par $x$, ce qui nous donnera une équation produit nul. +\begin{align*} +\numprint{-2}\,x^2 -\numprint{6}\,x &= 0 \\ +\numprint{-2}\,x\times x -\numprint{6}\times x &= 0 \\ +x\,\left( \numprint{-2}\,x -\numprint{6} \right) &= 0 \\ +\end{align*} +\begin{align*} +x =0 &\text{ ou } \numprint{-2}\,x -\numprint{6}=0 \\ +x =0 &\text{ ou } \numprint{-2}\,x =\numprint{6} \\ +x =0 &\text{ ou } x = \frac{\numprint{6}}{\numprint{-2}} \\ +x =0 &\text{ ou } x = \numprint{-3} \\ +\end{align*} +Il y a donc deux solutions : $x=0$ et $x=\numprint{-3}$. +\item $f\,(x)=\numprint{84.5}$ On remarque que la forme canonique contient la constante $\numprint{84.5}$ : en l'utilisant, elles devraient se simplifier. +\begin{align*} +f\,(x) &= \numprint{84.5} \\ +\numprint{-2} \,\left( x +\numprint{1.5} \right)^2 +\numprint{84.5} &= \numprint{84.5}\\ +\numprint{-2} \,\left( x +\numprint{1.5} \right)^2 +\numprint{84.5} -\numprint{84.5} &= \numprint{84.5} -\numprint{84.5}\\ +\numprint{-2} \,\left( x +\numprint{1.5} \right)^2 &= 0\\ +\left( x +\numprint{1.5} \right)^2 &= 0\\ +\end{align*} +Or $0$ est le seul nombre dont le carré est nul, donc l'équation précédente est équivalente à : +\begin{align*} +x +\numprint{1.5} &= 0\\ +x &= \numprint{-1.5} \\ +\end{align*} +Il y a donc une unique solution $x=\numprint{-1.5}$. +\end{enumerate} +\item +\begin{enumerate} +\item \emph{Dresser le tableau de variations de $f$.} Dans la forme développée, le coefficient devant le $x^2$ est + négatif , +donc la fonction est + croissante puis décroissante . +De plus, l'absisse du sommet est $-\frac{\numprint{-6}}{2\times\left(\numprint{-2}\right)}$, soit $\numprint{-1.5}$, et +$f\,( \numprint{-1.5} )=\numprint{-2}\times\left(\numprint{-1.5}\right)^2 -\numprint{6}\times \left(\numprint{-1.5}\right) +\numprint{80}=\numprint{84.5}$. +Le tableau de variations est donc : +\begin{center} + \begin{tikzpicture} + \tkzTabInit[espcl=2.5] + {$x$/1, $f\,(x)$/1.5} + {$-\infty$, $\numprint{-1.5}$, $+\infty$} + \tkzTabVar{-/, +/$\numprint{84.5}$/, -/} + \end{tikzpicture} +\end{center} +\item \emph{Dresser le tableau de signes de $f$.} Construisons un tableau de signes en utilisant la forme factorisée $f\,(x)=\numprint{-2} \,\left(x -\numprint{5}\right) \, \left(x +\numprint{8}\right)$. + +\begin{itemize} +\item Le premier facteur $x -\numprint{5}$ est une fonction affine, de coefficient directeur $a=1$ positif, et d'ordonnée à l'origine $b=\numprint{-5}$. Elle est donc négative, puis positive, et change de signe en $-\frac{b}{a}=-\frac{\numprint{-5}}{1}=\numprint{5}$. +\item Le second facteur $x +\numprint{8}$ est aussi une fonction affine, de coefficient directeur $a=1$ positif, et d'ordonnée à l'origine $b=\numprint{8}$. Elle est donc négative, puis positive, et change de signe en $-\frac{b}{a}=-\frac{\numprint{8}}{1}=\numprint{-8}$. +\end{itemize} +\begin{center} + \begin{tikzpicture} + \tkzTabInit[lgt=4, espcl=2.5] + { + $x$/1, + $\numprint{-2}$/1, + $x -\numprint{5}$/1, + $x +\numprint{8}$/1, + $f\,(x)=\numprint{-2}\,\left( x -\numprint{5} \right)\,\left( x +\numprint{8} \right)$/1.5 + } + {$-\infty$, $\numprint{-8}$, $\numprint{5}$, $+\infty$} + \tkzTabLine{, -, t, -, t, -} + \tkzTabLine{, -, t, -, z, +} + \tkzTabLine{, -, z, +, t, +} + \tkzTabLine{, -, z, +, z, -} + \end{tikzpicture} +\end{center} +\end{enumerate} +\item Répondre aux questions suivantes en utilisant le tableau de signes ou de variations. +\begin{enumerate} +\item \emph{Résoudre $f\,(x)\geqslant0$.} En regardant la dernière ligne du tableau de signes, on observe que $f$ est positive sur + l'intervalle central . +Les solutions sont donc : + \[ x\in\interval[scaled]{\numprint{-8}}{\numprint{5}} \] +\item \emph{Quel est l'extremum de $f$ ? Est-ce un maximum ou un minimum ? Pour quelle valeur de $x$ est-il atteint ?} On lit sur le tableau de variations que la plus + grande valeur prise par $f$ est $\numprint{84.5}$. Le + maximum de $f$ est donc $\numprint{84.5}$, et il est atteint pour $x=\numprint{-1.5}$. +\end{enumerate} +\end{enumerate} \ No newline at end of file diff --git a/data/ex/tests/BilanTrinomeSansDiscriminant.1.statement b/data/ex/tests/BilanTrinomeSansDiscriminant.1.statement new file mode 100644 index 00000000..ec799a4e --- /dev/null +++ b/data/ex/tests/BilanTrinomeSansDiscriminant.1.statement @@ -0,0 +1,26 @@ +\exercice +On considère le trinôme du second degré $f: x\mapsto \numprint{-2}\,x^2 -\numprint{6}\,x +\numprint{80}$. + +\begin{enumerate} +\item +\begin{enumerate} + \item Montrer que pour tout $x\in\mathbb{R}$, on a : $f\,(x)=\numprint{-2} \,\left( x -\numprint{5} \right) \, \left( x +\numprint{8} \right) $. + \item Montrer que pour tout $x\in\mathbb{R}$, on a : $f\,(x)=\numprint{-2} \,\left( x +\numprint{1.5} \right)^2 +\numprint{84.5}$. +\end{enumerate} +\item Résoudre les équations suivantes en choisissant la forme appropriée de $f$. +\begin{enumerate} +\item $f\,(x)=0$ +\item $f\,(x)=\numprint{80}$ +\item $f\,(x)=\numprint{84.5}$ +\end{enumerate} +\item +\begin{enumerate} +\item Dresser le tableau de variations de $f$. +\item Dresser le tableau de signes de $f$. +\end{enumerate} +\item Répondre aux questions suivantes en utilisant le tableau de signes ou de variations. +\begin{enumerate} +\item Résoudre $f(x)\geqslant0$. +\item Quel est l'extremum de $f$ ? Est-ce un maximum ou un minimum ? Pour quelle valeur de $x$ est-il atteint ? +\end{enumerate} +\end{enumerate} \ No newline at end of file diff --git a/data/ex/tests/EtatStableSysteme2.0.answer b/data/ex/tests/EtatStableSysteme2.0.answer new file mode 100644 index 00000000..5504a302 --- /dev/null +++ b/data/ex/tests/EtatStableSysteme2.0.answer @@ -0,0 +1,34 @@ +\exercice* +Puisque $P$ est l'état stable, alors $P=P\times M$. + +\begin{align*} + P\times M &= \begin{pmatrix}x&y\end{pmatrix}\times +\begin{pmatrix} + \numprint{0.95} & \numprint{0.05} \\ + \numprint{0.45} & \numprint{0.55} \\ +\end{pmatrix}\\ +&= \begin{pmatrix} + \numprint{0.95}\,x + \numprint{0.45}\,y & \numprint{0.05}\,x + \numprint{0.55}\,y +\end{pmatrix} +\end{align*} + +Or $\begin{pmatrix}x&y\end{pmatrix}=P=P\times M$, donc les coefficients des matrices sont deux à deux égaux, donc $x=\numprint{0.95}\,x + \numprint{0.45}\,y$. + +D'autre part, puisque $P$ est un état probabiliste, alors $x+y=1$, donc $y=1-x$. Donc, en remplaçant $y$ par $1-x$ dans l'équation précédente, on obtient : + +\begin{align*} + x &= \numprint{0.95}\,x + \numprint{0.45}\,(1-x) \\ + x &= \numprint{0.95}\,x + \numprint{0.45} - \numprint{0.45}\,x\\ + x-\numprint{0.95}\,x +\numprint{0.45}\,x &= \numprint{0.45}\\ + (1-\numprint{0.95}+\numprint{0.45}) \,x &= \numprint{0.45}\\ + \numprint{0.5}\,x &= \numprint{0.45}\\ + x &= \frac{\numprint{0.45}}{\numprint{0.5}}\\ +x &= \numprint{0.9} +\end{align*} + +Enfin, puisque $y=1-x$, alors $y=1-\numprint{0.9}=\numprint{0.1}$. + +L'unique état stable de ce graphe est donc $\begin{pmatrix} +\numprint{0.9} & +\numprint{0.1} +\end{pmatrix}$. \ No newline at end of file diff --git a/data/ex/tests/EtatStableSysteme2.0.statement b/data/ex/tests/EtatStableSysteme2.0.statement new file mode 100644 index 00000000..b77a24c2 --- /dev/null +++ b/data/ex/tests/EtatStableSysteme2.0.statement @@ -0,0 +1,11 @@ +\exercice +On considère un graphe probabiliste d'ordre 2, dont la matrice de transition est : + +\[ +M=\begin{pmatrix} + \numprint{0.95} & \numprint{0.05} \\ + \numprint{0.45} & \numprint{0.55} \\ +\end{pmatrix} +\] + +On note $P=\begin{pmatrix}x&y\end{pmatrix}$ l'état stable de ce graphe. Déterminer $x$ et $y$. \ No newline at end of file diff --git a/data/ex/tests/InterpolationMatrices.0.answer b/data/ex/tests/InterpolationMatrices.0.answer new file mode 100644 index 00000000..acb550c8 --- /dev/null +++ b/data/ex/tests/InterpolationMatrices.0.answer @@ -0,0 +1,63 @@ +\exercice* +\begin{enumerate} + + \item + \begin{enumerate} + \item + \begin{itemize} + \item Puisque $A\,( \numprint{4}~;~\numprint{-75} )$ est sur la courbe de $f$, alors $f\,( \numprint{4} )=\numprint{-75}$, soit + $a \times \numprint{4}^2+b\times \numprint{4}+c=\numprint{-75}$, + c'est-à-dire $\numprint{16}\,a + \numprint{4}\,b + c = \numprint{-75}$. + \item De même, puisque $B\,( \numprint{5}~;~\numprint{-126} )$ est sur la courbe de $f$, alors $f\,( \numprint{5} )=\numprint{-126}$, soit + $a \times \numprint{5}^2+b\times \numprint{5}+c=\numprint{-126}$, + c'est-à-dire $\numprint{25}\,a + \numprint{5}\,b + c = \numprint{-126}$. + \item Enfin, puisque $C\,( \numprint{6}~;~\numprint{-191} )$ est sur la courbe de $f$, alors $f\,( \numprint{6} )=\numprint{-191}$, soit + $a \times \numprint{6}^2+b\times \numprint{6}+c=\numprint{-191}$, + c'est-à-dire $\numprint{36}\,a + \numprint{6}\,b + c = \numprint{-191}$. + \end{itemize} + + On en déduit le système suivant : + \[ \left\{\begin{array}{rcl} + \numprint{16}\,a + \numprint{4}\,b + c &=& \numprint{-75} \\ + \numprint{25}\,a + \numprint{5}\,b + c &=& \numprint{-126} \\ + \numprint{36}\,a + \numprint{6}\,b + c &=& \numprint{-191} \\ + \end{array}\right.\] + \item + +\begin{align*} + \left\{\begin{array}{rcl} + \numprint{16}\,a + \numprint{4}\,b + c &=& \numprint{-75} \\ + \numprint{25}\,a + \numprint{5}\,b + c &=& \numprint{-126} \\ + \numprint{36}\,a + \numprint{6}\,b + c &=& \numprint{-191} \\ + \end{array}\right. +&\iff +\begin{pmatrix} +\numprint{16}\,a + \numprint{4}\,b + c \\ +\numprint{25}\,a + \numprint{5}\,b + c \\ +\numprint{36}\,a + \numprint{6}\,b + c \\ +\end{pmatrix} = \begin{pmatrix}\numprint{-75}\\\numprint{-126}\\\numprint{-191}\\\end{pmatrix}\\ +&\iff +\begin{pmatrix}\numprint{16} & \numprint{4} & \numprint{1}\\\numprint{25} & \numprint{5} & \numprint{1}\\\numprint{36} & \numprint{6} & \numprint{1}\\\end{pmatrix} \times \begin{pmatrix}a\\b\\c\\\end{pmatrix} = \begin{pmatrix}\numprint{-75}\\\numprint{-126}\\\numprint{-191}\\\end{pmatrix} \\ +&\iff M\, X=R +\end{align*} + + Avec : $M= \begin{pmatrix}\numprint{16} & \numprint{4} & \numprint{1}\\\numprint{25} & \numprint{5} & \numprint{1}\\\numprint{36} & \numprint{6} & \numprint{1}\\\end{pmatrix}$, $X= \begin{pmatrix}a\\b\\c\\\end{pmatrix}$ et $R= \begin{pmatrix}\numprint{-75}\\\numprint{-126}\\\numprint{-191}\\\end{pmatrix}$. + \end{enumerate} + \item + Comme $M$ est inversible, et que $M\,X = R$, alors $X = M^{-1}\times R$. + + À la calculatrice, on obtient + $M^{-1}\times R=\begin{pmatrix}\numprint{16} & \numprint{4} & \numprint{1}\\\numprint{25} & \numprint{5} & \numprint{1}\\\numprint{36} & \numprint{6} & \numprint{1}\\\end{pmatrix}^{-1}\times \begin{pmatrix}\numprint{-75}\\\numprint{-126}\\\numprint{-191}\\\end{pmatrix} = \begin{pmatrix}\numprint{-7}\\\numprint{12}\\\numprint{-11}\\\end{pmatrix}$. + + Ainsi, $a=\numprint{-7}$, $b=\numprint{12}$, et $c=\numprint{-11}$. + \item +En utilisant les valeurs de $a$, $b$, et $c$ calculées précédemment, nous connaissons l'expression de la fonction : $f\,(x) = \numprint{-7}\,x^2 +\numprint{12}\,x -\numprint{11}$. + +Nous pouvons maintenant calculer l'image de $\numprint{17}$ par cette fonction : +\begin{align*} +f\,( \numprint{17} ) +&= \numprint{-7} \times \numprint{17}^2 +\numprint{12} \times \numprint{17} -\numprint{11}\\ +&= \numprint{-1830} +\end{align*} +Donc $f\,( \numprint{17} ) = \numprint{-1830}$. +\end{enumerate} diff --git a/data/ex/tests/InterpolationMatrices.0.statement b/data/ex/tests/InterpolationMatrices.0.statement new file mode 100644 index 00000000..e2761d29 --- /dev/null +++ b/data/ex/tests/InterpolationMatrices.0.statement @@ -0,0 +1,25 @@ +\exercice +Dans un repère orthonormé, on cherche à déterminer l'équation d'une fonction dont la courbe passe par les points +$A\,( \numprint{4} ~;~ \numprint{-75} )$, +$B\,( \numprint{5} ~;~ \numprint{-126} )$ et +$C\,( \numprint{6} ~;~ \numprint{-191} )$. + +On cherche un trinôme du second degré, c'est-à-dire une fonction $f$ définie sur $\interval[open]{-\infty}{+\infty}$ par + \mbox{$f\,(x) = a\,x^2 + b\,x + c$} où $a$, $b$ et $c$ sont trois nombres réels, que l'on cherche à déterminer. + + \begin{enumerate} + \item + \begin{enumerate} + \item À partir des données de l'énoncé, écrire un système d'équations traduisant cette situation. + \item En déduire que le système précédent est équivalent à : $M\,X = R$ avec + + $M = \begin{pmatrix}\numprint{16} & \numprint{4} & \numprint{1}\\\numprint{25} & \numprint{5} & \numprint{1}\\\numprint{36} & \numprint{6} & \numprint{1}\\\end{pmatrix}$, $X= \begin{pmatrix}a\\b\\c\\\end{pmatrix}$ et $R$ une matrice colonne que l'on précisera. + \end{enumerate} + \end{enumerate} + \begin{enumerate} + \setcounter{enumi}{1} + \item On admet que la matrice $M$ est inversible. + Déterminer les valeurs des cœfficients $a$, $b$ et $c$, en détaillant les calculs. + \item Quelle est la valeur de $f\,( \numprint{17} )$ ? + + \end{enumerate} \ No newline at end of file diff --git a/data/templates/evaluation.tex b/data/templates/evaluation.tex index 2f029ec3..3e8e870c 100644 --- a/data/templates/evaluation.tex +++ b/data/templates/evaluation.tex @@ -21,6 +21,7 @@ \usepackage{wrapfig} % allows figures or tables to have text wrapped around \usepackage{pst-eucl, pst-plot} % figures géométriques \usepackage{enumitem} +\usepackage{interval} \usepackage{wasysym} % Symbole Euro \usepackage{mathtools} % Encadrement dans align* \usepackage[inline]{asymptote} @@ -35,6 +36,7 @@ ps2eps -f "\image.ps" } } +\intervalconfig{ separator symbol={\,;\,}} %\usepackage{textcomp} diff --git a/data/templates/pyromaths.tex b/data/templates/pyromaths.tex index f6c0b071..c58168b4 100644 --- a/data/templates/pyromaths.tex +++ b/data/templates/pyromaths.tex @@ -21,6 +21,7 @@ \usepackage{wrapfig} % allows figures or tables to have text wrapped around \usepackage{pst-eucl, pst-plot} % figures géométriques \usepackage{enumitem} +\usepackage{interval} \usepackage{wasysym} % Symbole Euro \usepackage{mathtools} % Encadrement dans align* \usepackage[inline]{asymptote} @@ -35,6 +36,7 @@ ps2eps -f "\image.ps" } } +\intervalconfig{ separator symbol={\,;\,}} %\usepackage{textcomp} diff --git a/locale/ca@valencia/LC_MESSAGES/pyromaths.po b/locale/ca@valencia/LC_MESSAGES/pyromaths.po index ee757005..6e7cf3e3 100644 --- a/locale/ca@valencia/LC_MESSAGES/pyromaths.po +++ b/locale/ca@valencia/LC_MESSAGES/pyromaths.po @@ -2808,7 +2808,7 @@ msgid "Sens de variations" msgstr "Intervals de monotonia" #: src/pyromaths/ex/lycee/ExoPolynome.py:284 -msgid "0.Term STG" +msgid "0.Term STMG" msgstr "0.2n Batxillerat" #: src/pyromaths/ex/lycee/ExoPolynome.py:302 diff --git a/locale/en/LC_MESSAGES/pyromaths.po b/locale/en/LC_MESSAGES/pyromaths.po index f341bcc9..e2226c26 100644 --- a/locale/en/LC_MESSAGES/pyromaths.po +++ b/locale/en/LC_MESSAGES/pyromaths.po @@ -1851,7 +1851,7 @@ msgid "Sens de variations" msgstr "" #: src/pyromaths/ex/lycee/ExoPolynome.py:284 -msgid "0.Term STG" +msgid "0.Term STMG" msgstr "" #: src/pyromaths/ex/lycee/ExoPolynome.py:302 diff --git a/locale/es/LC_MESSAGES/pyromaths.po b/locale/es/LC_MESSAGES/pyromaths.po index 1466d39b..7a2a6c56 100644 --- a/locale/es/LC_MESSAGES/pyromaths.po +++ b/locale/es/LC_MESSAGES/pyromaths.po @@ -2566,7 +2566,7 @@ msgid "Sens de variations" msgstr "Las variaciones en el significado" #: src/pyromaths/ex/lycee/ExoPolynome.py:284 -msgid "0.Term STG" +msgid "0.Term STMG" msgstr "0.2º Bachillerato" #: src/pyromaths/ex/lycee/ExoPolynome.py:302 diff --git a/locale/pl/LC_MESSAGES/pyromaths.po b/locale/pl/LC_MESSAGES/pyromaths.po index f0d8a6fe..04cb9047 100644 --- a/locale/pl/LC_MESSAGES/pyromaths.po +++ b/locale/pl/LC_MESSAGES/pyromaths.po @@ -1849,7 +1849,7 @@ msgid "Sens de variations" msgstr "" #: src/pyromaths/ex/lycee/ExoPolynome.py:284 -msgid "0.Term STG" +msgid "0.Term STMG" msgstr "" #: src/pyromaths/ex/lycee/ExoPolynome.py:302 diff --git a/locale/pyromaths.pot b/locale/pyromaths.pot index 75b2458c..c9ea5ab9 100644 --- a/locale/pyromaths.pot +++ b/locale/pyromaths.pot @@ -1849,7 +1849,7 @@ msgid "Sens de variations" msgstr "" #: src/pyromaths/ex/lycee/ExoPolynome.py:284 -msgid "0.Term STG" +msgid "0.Term STMG" msgstr "" #: src/pyromaths/ex/lycee/ExoPolynome.py:302 diff --git a/setup.py b/setup.py index c0b75977..94526d51 100755 --- a/setup.py +++ b/setup.py @@ -58,6 +58,8 @@ from pyromaths.Values import VERSION print "Version ", VERSION +COMMON_INSTALL_REQUIRES = ['jinja2'] + def _unix_opt(): '''UNIX/Linux: generate Python eggs and RPM packages.''' return dict( @@ -73,7 +75,7 @@ def _unix_opt(): # ('share/pyromaths/packages', glob('data/packages/*')) ] + \ find_data_files('data/ex','share/pyromaths/ex/',['img/*.png']), - install_requires = ["lxml>=2.2.2"], + install_requires = COMMON_INSTALL_REQUIRES + ["lxml>=2.2.2"], ) def _mac_opt(): @@ -126,8 +128,9 @@ def _mac_opt(): 'data/images/whatsthis.png']), ('data/templates', glob('data/templates/*.tex')), # ('data/packages', glob('data/packages/*')), - ] + find_data_files('data/ex','data/ex/',['img/*.png']), + ] + find_data_files('data/ex','data/ex/',['img/*.png', 'templates/*.tex']), setup_requires = ['py2app>=0.7.3', 'lxml>=2.2.2'], + install_requires = COMMON_INSTALL_REQUIRES, options = {'py2app': py2app}, ) @@ -161,6 +164,7 @@ def _win_opt(): ) ], setup_requires = ['py2exe'], + install_requires = COMMON_INSTALL_REQUIRES, options = dict(py2exe=dict(compressed = True, optimize = 2, bundle_files = 3, diff --git a/src/pyromaths/cli/__main__.py b/src/pyromaths/cli/__main__.py index e85c01bc..5d1c234e 100755 --- a/src/pyromaths/cli/__main__.py +++ b/src/pyromaths/cli/__main__.py @@ -117,6 +117,13 @@ def argument_parser(): ) gui.add_argument('args', nargs=argparse.REMAINDER) + # Dummy + dummy = subparsers.add_parser( + 'dummy', + help='Generate a dummy LaTeX file.', + ) + dummy.add_argument('args', nargs=argparse.REMAINDER) + return parser def do_test(options): @@ -130,6 +137,11 @@ def do_gui(options): sys.argv = ["pyromaths"] + sys.argv[2:] pyromaths.main() +def do_dummy(options): + """Action for command line 'dummy'.""" + from . import dummy + dummy.main() + def do_generate(options): """Action for command line 'generate'.""" tests = TestPerformer() @@ -155,7 +167,7 @@ def do_generate(options): def do_ls(options): # pylint: disable=unused-argument """Perform the `ls` command.""" tests = TestPerformer() - for name in sorted(tests.iter_names()): + for name in sorted(tests.iter_names(), key=str.lower): if options.verbose: print(u"{}: {}".format(name, tests.exercises[name].description)) # pylint: disable=superfluous-parens else: @@ -166,6 +178,7 @@ def do_ls(options): # pylint: disable=unused-argument "ls": do_ls, "test": do_test, "gui": do_gui, + "dummy": do_dummy, } def main(): diff --git a/src/pyromaths/cli/dummy.py b/src/pyromaths/cli/dummy.py new file mode 100644 index 00000000..cf63ed3f --- /dev/null +++ b/src/pyromaths/cli/dummy.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright (C) 2018 -- Louis Paternault (spalax@gresille.org) +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +"""Création d'un modèle d'exercice.""" + +import logging +import os +import textwrap + +from pyromaths.Values import CONFIGDIR, DATADIR +from pyromaths.ex import TexExercise +from pyromaths.outils.System import creation + +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s %(message)s', + ) + +class DummyExercise(TexExercise): + """Faux exercice, servant de modèle pour les nouveaux exercices.""" + + def tex_statement(self): + return [textwrap.dedent(ur"""\ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % DÉBUT DE L'ÉNONCÉ + \exercice + + ÉNONCÉ DE L'EXERCICE + + % FIN DE L'ÉNONCÉ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + """)] + + def tex_answer(self): + return [textwrap.dedent(ur"""\ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % DÉBUT DU CORRIGÉ + \exercice* + + CORRIGÉ DE L'EXERCICE + + % FIN DU CORRIGÉ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + """)] + +PARAMETRES = { + 'nom_fichier': u'exercices', + 'corrige': True, + 'les_fiches': [[u'0.modele', '', [DummyExercise]]], + 'fiche_exo': os.path.join(os.getcwd(), "exercices.tex"), + 'creer_unpdf': True, + 'configdir': CONFIGDIR, + 'niveau': u'Modèle', + 'creer_pdf': True, + 'datadir': DATADIR, + 'chemin_fichier': os.getcwd(), + 'modele': u'pyromaths.tex', + 'titre': u'Modèle', + 'fiche_cor': os.path.join(os.getcwd(), "exercices-corrige.tex"), + 'liste_exos': [DummyExercise()], + } + +def main(): + """Fonction principale.""" + creation(PARAMETRES) + logging.info("Le modèle de document est disponible dans le fichier `exercices.tex`.") + +if __name__ == "__main__": + main() diff --git a/src/pyromaths/ex/__init__.py b/src/pyromaths/ex/__init__.py index 87d0ff28..eac00ced 100644 --- a/src/pyromaths/ex/__init__.py +++ b/src/pyromaths/ex/__init__.py @@ -7,6 +7,8 @@ import types import sys +import jinja2 + class Exercise(object): ''' Base class for all exercise types. ''' @@ -176,3 +178,57 @@ def load_levels(pkg=None, recursive=True): levels[lvl] = sublevels[lvl] return levels + +################################################################################ +# Exercices créés à partir de templates Jinja2 + +def templatedir(): + from pyromaths import Values + return os.path.join( + Values.data_dir(), + "ex", + "templates", + ) + +class Jinja2Exercice(TexExercise): + """Exercice utilisant un template jinja2.""" + + def __init__(self): + super(Jinja2Exercice, self).__init__() + self.context = {} + + @property + def environment(self): + """Création de l'environnement Jinja2, duquel sera chargé le template.""" + environment = jinja2.Environment( + loader=jinja2.FileSystemLoader(templatedir()) + ) + environment.block_start_string = '(*' + environment.block_end_string = '*)' + environment.variable_start_string = '((' + environment.variable_end_string = '))' + environment.comment_start_string = '(% ' + environment.comment_end_string = ' %)' + environment.trim_blocks = True + environment.lstrip_blocks = True + + return environment + + @property + def statement_name(self): + """Nom du fichier de l'énoncé (sans le répertoire).""" + return os.path.join("{}-statement.tex".format(self.__class__.__name__)) + + @property + def answer_name(self): + """Nom du fichier du corrigé (sans le répertoire).""" + return os.path.join("{}-answer.tex".format(self.__class__.__name__)) + + def tex_statement(self): + """Génération de l'énoncé""" + return [self.environment.get_template(self.statement_name).render(self.context)] + + def tex_answer(self): + """Génération du corrigé""" + return [self.environment.get_template(self.answer_name).render(self.context)] + diff --git a/src/pyromaths/ex/lycee/ExoPolynome.py b/src/pyromaths/ex/lycee/ExoPolynome.py index 336286d4..01e5bbf7 100644 --- a/src/pyromaths/ex/lycee/ExoPolynome.py +++ b/src/pyromaths/ex/lycee/ExoPolynome.py @@ -281,7 +281,7 @@ def exo_variation(): return exo, cor exo_variation.description = _(u"Sens de variations") -exo_variation.level = [_(u"1.1èreS"), _(u"0.Term STG")] +exo_variation.level = [_(u"1.1èreS"), _(u"0.Term STMG")] def exo_variation_lim(): diff --git a/src/pyromaths/ex/lycee/TermesSuite.py b/src/pyromaths/ex/lycee/TermesSuite.py index 07d08f29..97cfd361 100644 --- a/src/pyromaths/ex/lycee/TermesSuite.py +++ b/src/pyromaths/ex/lycee/TermesSuite.py @@ -21,16 +21,12 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # -from pyromaths import ex import functools -from math import sqrt import random -from pyromaths.outils import Priorites3 import textwrap -from pyromaths.classes.Fractions import Fraction -from pyromaths.classes.PolynomesCollege import Polynome, factoriser -from pyromaths.classes.SquareRoot import SquareRoot -from pyromaths.outils.Arithmetique import carrerise, pgcd, valeur_alea + +from pyromaths import ex +from pyromaths.outils.Arithmetique import pgcd FRANCAIS_ORDINAL = { 1: u"premier", diff --git a/src/pyromaths/ex/lycee/matrices.py b/src/pyromaths/ex/lycee/matrices.py new file mode 100644 index 00000000..3c57a93d --- /dev/null +++ b/src/pyromaths/ex/lycee/matrices.py @@ -0,0 +1,145 @@ +# -*- coding: utf-8 -*- +# +# Pyromaths +# +# Un programme en Python qui permet de créer des fiches d'exercices types de +# mathématiques niveau collège ainsi que leur corrigé en LaTeX. +# +# Copyright (C) 2018 -- Louis Paternault (spalax@gresille.org) +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +"""Exercice de Terminale ES, spécialité : Déterminer un état stable en utilisant un système.""" + +import decimal +import random + +from pyromaths.ex import Jinja2Exercice +from pyromaths.outils.jinja2 import facteur, matrice + +# Liste des coefficients de la diagonale de la matrice de transition qui +# donnent des états stables dont la valeur exacte a au plus trois décimales. +CANDIDATS = [ + [.45, .30], + [.50, .25], + [.55, .20], + [.55, .25], + [.60, .15], + [.65, .10], + [.70, .05], + [.70, .10], + [.70, .50], + [.70, .55], + [.75, .45], + [.80, .40], + [.80, .70], + [.85, .40], + [.85, .55], + [.85, .65], + [.85, .75], + [.90, .30], + [.95, .55], + [.95, .65], + [.95, .80], + [.95, .85], + ] + + +class EtatStableSysteme2(Jinja2Exercice): + + description = u"Recherche d'état stable (avec un système)" + level = u"0.Term ES" + + def __init__(self): + super(EtatStableSysteme2, self).__init__() + + ab = random.choice(CANDIDATS) + random.shuffle(ab) + self.context = { + "a": ab[0], + "b": ab[1], + } + + @property + def environment(self): + environment = super(EtatStableSysteme2, self).environment + environment.filters.update({ + 'facteur': facteur, + }) + return environment + +class InterpolationMatrices(Jinja2Exercice): + # Plus ou moins inspiré du sujet de bac ES Amérique du Nord, juin 2015. + + description = u"Interpolation polynomiale en utilisant des matrices" + level = u"0.Term ES" + + def __init__(self): + super(InterpolationMatrices, self).__init__() + + X = [None, None, None] + while len(set(X)) != 3: + X = sorted([ + random.randint(2, 9), + random.randint(2, 9), + random.randint(2, 9), + ]) + + a = b = c = 0 + while True: + a = decimal.Decimal(random.choice([1, -1]) * random.randint(2, 19)) + b = decimal.Decimal(random.choice([1, -1]) * random.randint(2, 19)) + c = decimal.Decimal(random.choice([1, -1]) * random.randint(2, 19)) + + if len(set([a, b, c])) != 3: + continue + if 10 in (abs(a), abs(b), abs(c)): + continue + break + + if random.randint(0, 1) == 1: + a = a / 10 + b = b / 10 + c = c / 10 + + M = [ + [X[0]**2, X[0], 1], + [X[1]**2, X[1], 1], + [X[2]**2, X[2], 1], + ] + Y = [ + a * X[0]**2 + b * X[0] + c, + a * X[1]**2 + b * X[1] + c, + a * X[2]**2 + b * X[2] + c, + ] + + self.context = { + "X": X, + "Y": Y, + "A": [a, b, c], + "M": M, + "x": random.randint(10, 19), + } + + @property + def environment(self): + environment = super(InterpolationMatrices, self).environment + environment.filters.update({ + 'facteur': facteur, + 'matrice': matrice, + 'zip': zip, + }) + return environment diff --git a/src/pyromaths/ex/lycee/seconddegre.py b/src/pyromaths/ex/lycee/seconddegre.py new file mode 100644 index 00000000..d9605bb2 --- /dev/null +++ b/src/pyromaths/ex/lycee/seconddegre.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +# +# Pyromaths +# +# Un programme en Python qui permet de créer des fiches d'exercices types de +# mathématiques niveau collège ainsi que leur corrigé en LaTeX. +# +# Copyright (C) 2018 -- Louis Paternault (spalax@gresille.org) +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +"""Exercice de seconde : Chapitre Second degré.""" + +import random + +from pyromaths.ex import Jinja2Exercice +from pyromaths.outils.jinja2 import facteur + +def signe(nombre): + """Renvoit une chaîne contenant le signe de l'argument.""" + if nombre < 0: + return "-" + return "+" + +class BilanTrinomeSansDiscriminant(Jinja2Exercice): + + description = u"Bilan sur les trinômes" + level = u"2.Seconde" + + def __init__(self): + super(BilanTrinomeSansDiscriminant, self).__init__() + + while True: + a = float(random.choice([-1, 1]) * random.choice([0.5, 2])) + x1 = float(random.choice([-1, 1]) * random.randint(2, 15)) + x2 = float(random.choice([-1, 1]) * random.randint(2, 15)) + + b = -a * (x1 + x2) + c = a * x1 * x2 + + alpha = -b/(2*a) + beta = a * (alpha**2) + b * alpha + c + + if alpha == 0 or beta == 0: + continue + if b == 0 or c == 0: + continue + if beta == c: + continue + + break + + self.context = { + "a": a, + "b": b, + "c": c, + "x1": x1, + "x2": x2, + "alpha": alpha, + "absalpha": abs(alpha), # Valeur absolue de alpha + "signealpha": alpha/abs(alpha), # Signe de alpha (qui est non nul) + "beta": beta, + } + + @property + def environment(self): + environment = super(BilanTrinomeSansDiscriminant, self).environment + environment.filters.update({ + 'facteur': facteur, + 'min': min, + 'max': max, + 'abs': abs, + 'signe': signe, + }) + return environment diff --git a/src/pyromaths/outils/TexFiles.py b/src/pyromaths/outils/TexFiles.py index 2dac38f6..b49f7887 100644 --- a/src/pyromaths/outils/TexFiles.py +++ b/src/pyromaths/outils/TexFiles.py @@ -44,7 +44,7 @@ def mise_en_forme(file): cline = cline.strip() indent = trouve_indentation(cline, indent, lline) if indent < 0: - print _("problème") + print _(u"problème") if cline: chaine, indent = traite_chaine(cline, indent) new_tex.extend(chaine) diff --git a/src/pyromaths/outils/jinja2.py b/src/pyromaths/outils/jinja2.py new file mode 100644 index 00000000..defa2fb4 --- /dev/null +++ b/src/pyromaths/outils/jinja2.py @@ -0,0 +1,302 @@ +# -*- coding: utf-8 -*- + +# Pyromaths +# +# Un programme en Python qui permet de créer des fiches d'exercices types de +# mathématiques niveau collège ainsi que leur corrigé en LaTeX. +# +# Copyright (C) 2018 -- Louis Paternault (spalax@gresille.org) +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +"""Outils à utiliser avec les exercices utilisant Jinja2. +""" + +import math +import numbers + +def facteur(nombre, court="", + parentheses=False, + zero=False, + arrondi=None, + signe=False, + operation=False, + produit=False, + variable="", + ): + r"""Renvoit le code :math:`\LaTeX` correspondant au nombre, dans un ``\\numprint{}``, en gérant de nombreux cas particuliers. + + Les cas d'utilisation de cette fonction sont détaillés dans le :ref:`tutoriel pour écrire un nouvel exercice `. + + En utilisant les arguments, cette fonction permet de prendre en compte les arrondis, et de nombreux cas particuliers (dans chaque cas, c'est le 3 qui est destiné à être rendu par cette fonction. + + - ajout de parenthèses uniquement si nécessaire (produit `2×3` et `2×(-3)` plutôt que `2×-3` ou `2×(3)`) ; + - ajout du signe, même s'il est positif (produit `1+3x` et `1-3x` plutôt que `1 3x` ou `1+-3x`) ; + - n'affiche pas le nombre 1, et seulement le signe de -1 (produit `x` et `-x` plutôt que `1x` et `-1x`) ; + - n'affiche pas l'opérande nulle d'un produit (produit `2` plutôt que `2+0x`) ; + - etc. + + Le séparateur décimal est le point, mais celui-ci sera converti en une virgule par ``\\numprint{}``. + + :param float nombre: Nombre à formatter. + :param str court: Version courte des arguments (voir plus loin). + :param boolean parentheses: Encadre le nombre avec des parenthèses, s'il est négatif (utile pour produire `2×(-3)` plutôt que `2×3`). + :param int arrondi: Arrondi le nombre. L'argument est le nombre de chiffres après la virgule à utiliser. Mettre cet argument à ``None`` pour ne pas arrondir. + :param boolean zero: Ajoute des zéros à la fin du nombre pour avoir autant de chiffres que défini par `arrondi` (par exemple, avec cette option et un arrondi au centième, `2` devient `2.00`). + :param boolean signe: Produit le signe, même si le nombre est positif (produit alors un +). + :param boolean operation: Indique que le signe plus ou moins est une opération (comme `2-3`) et non pas un opérateur unaire (comme `2×(-3)`). Cela a pour effet d'espacer un peu le signe du nombre. + :param boolean produit: Le facteur est une opérande d'un produit : le nombre 1 ne doit pas être affiché ; du nombre -1, on ne conserve que le signe ; rien n'est affiché si le nombre est 0 (pour produire `x`, `-x` ou rien plutôt que `1x`, `-1x`, `0x`). + :param str variable: Seconde opérande du produit. Doit être du code :math:`LaTeX` valide. + :return: Le nombre, formatté comme du code :math:`LaTeX`. + :rtype: str + + :Dépendances entre arguments: + + - Le comportement n'est pas défini si les arguments ``operation`` et ``parentheses`` sont utilisées en même temps. + + :Version courte des arguments: + + Pour que les arguments soient moins verbeux, il est possible d'utiliser la version courte des arguments. Par exemple, ``facteur(2, produit=True, parentheses=True, arrondi=3)`` peut s'écrire comme ``facteur(2, '*p3')``. + + Cet argument est une chaîne de caractères, chaque caractère « activant » une option longue. Par exemple ``*p3`` active les options ``produit``, ``parentheses`` et ``arrondi=3``. L'ordre des caractères n'a aucune importance. Plusieurs comportement sont non-définis : + + - présence de caractères ne correspondant à aucun argument ; + - utilisation conjointe des arguments courts et longs ; + - utilisation de plusieurs chiffres (pour l'argument ``arrondi``). + + Les arguments sont : + + - ``p``: ``parentheses`` ; + - ``z``: ``zero`` ; + - ``s``: ``signe`` ; + - ``o``: ``operation`` ; + - ``*``: ``produit`` ; + - chiffres ``0`` à ``9``: ``arrondi`` à l'entier correspondant ; + - ``x``, ``X``, ``y``, ``Y``: Raccourcis pour (respectivement) ``variable="x"``, ``variable="x^2"``, ``variable="y"``, ``variable="y^2"``. + + :Exemples: + + Cas de base + >>> facteur(2) + '\\numprint{2}' + >>> facteur(2.0) + '\\numprint{2}' + >>> facteur(2.3) + '\\numprint{2.3}' + >>> facteur(-122.0) + '\\numprint{-122}' + + Arrondi + >>> facteur(12345.6789, arrondi=None) + '\\numprint{12345.6789}' + >>> facteur(12345.6789, arrondi=0) + '\\numprint{12346}' + >>> facteur(12345.6789, arrondi=2) + '\\numprint{12345.68}' + >>> facteur(.6789, arrondi=0) + '\\numprint{1}' + >>> facteur(.6789, arrondi=2) + '\\numprint{0.68}' + + Zéro + >>> facteur(12345.6789, arrondi=None, zero=True) + '\\numprint{12345.6789}' + >>> facteur(12345, arrondi=2, zero=True) + '\\numprint{12345.00}' + >>> facteur(12345, arrondi=2, zero=False) + '\\numprint{12345}' + >>> facteur(12345.7, arrondi=2, zero=True) + '\\numprint{12345.70}' + >>> facteur(12345.7, arrondi=2, zero=False) + '\\numprint{12345.7}' + + Parenthèse + >>> facteur(-2, parentheses=True) + '\\left(\\numprint{-2}\\right)' + >>> facteur(2, parentheses=True) + '\\numprint{2}' + + Signe + >>> facteur(-2, signe=True) + '\\numprint{-2}' + >>> facteur(2, signe=True) + '\\numprint{+2}' + >>> facteur(2, signe=False) + '\\numprint{2}' + + Opération + >>> facteur(-2, operation=False) + '\\numprint{-2}' + >>> facteur(2, signe=True, operation=False) + '\\numprint{+2}' + >>> facteur(-2, operation=True) + '-\\numprint{2}' + >>> facteur(2, signe=True, operation=True) + '+\\numprint{2}' + + Produit + >>> facteur(1, produit=True, variable="x") + 'x' + >>> facteur(-1, produit=True, variable="x") + '-x' + >>> facteur(0, produit=True, variable="x") + '' + >>> facteur(1, produit=False, variable="x") + '\\numprint{1}\\,x' + + Variable + >>> facteur(2, variable='x') + '\\numprint{2}\\,x' + >>> facteur(-1, produit=True, variable='x') + '-x' + + Version courte des arguments + >>> facteur(-2, court="2zXo") + '-\\numprint{2.00}\\,x^2' + >>> facteur(-2, court="2zXp") + '\\left(\\numprint{-2.00}\\,x^2\\right)' + >>> facteur(-2, court="2zY") + '\\numprint{-2.00}\\,y^2' + >>> facteur(-1, court="y*") + '-y' + >>> facteur(1, court="p*x") + 'x' + >>> facteur(-1, court="p*x") + '\\left(-x\\right)' + >>> facteur(-2, court="p*x") + '\\left(\\numprint{-2}\\,x\\right)' + >>> facteur(2, court="p*x") + '\\numprint{2}\\,x' + >>> facteur(1, court="s*x") + '+x' + + """ + + # Format court des arguments + if "p" in court: + parentheses = True + if "z" in court: + zero = True + if "s" in court: + signe = True + if "o" in court: + operation = True + if "*" in court: + produit = True + if "x" in court: + variable = "x" + if "y" in court: + variable = "y" + if "X" in court: + variable = "x^2" + if "Y" in court: + variable = "y^2" + for entier in range(10): + if str(entier) in court: + arrondi = entier + + # Cas particuliers : produit + if produit: + if nombre == 1: + if operation or signe: + return "+{}".format(variable) + return variable + if nombre == -1: + if operation: + return "-{}".format(variable) + if parentheses: + return r"\left(-{}\right)".format(variable) + return "-{}".format(variable) + if nombre == 0: + return "" + + # Division du nombre en signe et valeur absolue + absolu = abs(nombre) + if signe and nombre >= 0: + plusoumoins = '+' + elif nombre < 0: + plusoumoins = '-' + else: + plusoumoins = '' + + # Conversion du nombre en prenant compte de l'arrondi et des zéros + # Je n'ai pas réussi à faire ça uniquement à coup de + # str.format(). Je serai ravi si quelqu'un me prouvait que + # c'est possible ! + if arrondi is None: + if math.trunc(absolu) == absolu: + strabsolu = str(int(absolu)) + else: + strabsolu = str(absolu) + elif arrondi == 0: + strabsolu = "{:g}".format(round(absolu)) + else: + entier = math.trunc(absolu) + decimal = str(round(absolu - entier, arrondi))[2:] + if zero: + strabsolu = "{}.{:0<{arrondi}}".format(entier, decimal, arrondi=arrondi) + elif entier == absolu: + strabsolu = str(entier) + else: + strabsolu = "{}.{}".format(entier, decimal) + + # Ajout éventuel d'une espace devant la variable + if variable: + variable = r"\," + variable + + # Ajout éventuel des parenthèses + if parentheses and nombre < 0: + formatter = r"\left(\numprint{{{signe}{absolu}}}{variable}\right)" + elif operation: + formatter = r"{signe}\numprint{{{absolu}}}{variable}" + else: + formatter = r"\numprint{{{signe}{absolu}}}{variable}" + + # Enfin ! + return formatter.format( + signe=plusoumoins, + absolu=strabsolu, + variable=variable, + ) + +def iter_facteurs(liste, short): + """Applique :func:`facteur` à une liste de nombres. + + - Les éléments peuvent être des nombres, ou pas (auquel cas la fonction :func:`str` est appliquée). + - L'argument ``short`` est transmis à :func:`facteur`. + """ + for element in liste: + if isinstance(element, numbers.Number): + yield facteur(element, short) + else: + yield str(element) + +def matrice(listes, short=""): + r"""Renvoit le code LaTeX d'une matrice. + + - La matrice est sous la forme d'une liste de lignes (où chaque ligne est une liste de coefficients). + - L'argument ``short`` est transmis à :func:`facteur`. + + >>> matrice([[1, 2], [3, 4]]) + u'\\begin{pmatrix}\\numprint{1} & \\numprint{2}\\\\\\numprint{3} & \\numprint{4}\\\\\\end{pmatrix}' + """ + text = u"" + text += r"\begin{pmatrix}" + for ligne in listes: + text += " & ".join(iter_facteurs(ligne, short)) + text += r"\\" + text += r"\end{pmatrix}" + + return text