# 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
[docs]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 <ecrire-facteur>`.
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``, ``n``, ``N`` : Raccourcis pour (respectivement) ``variable="x"``, ``variable="x^2"``, ``variable="y"``, ``variable="y^2"``, ``variable="n"``, ``variable="n^2"``.
:Exemples:
Cas de base
>>> from pyromaths.outils.jinja2utils import facteur
>>> 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")
<BLANKLINE>
>>> 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 "n" in court:
variable = "n"
if "X" in court:
variable = "x^2"
if "Y" in court:
variable = "y^2"
if "N" in court:
variable = "n^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,
)
[docs]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)
[docs]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`.
>>> from pyromaths.outils.jinja2utils import matrice
>>> matrice([[1, 2], [3, 4]])
\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