Compare commits

..

6 Commits

15 changed files with 86 additions and 614 deletions

View File

@ -11,7 +11,8 @@ import logging
from pathlib import Path from pathlib import Path
import pytex import pytex
from mapytex import Expression, Integer, Decimal from mapytex import Expression, Integer, Decimal, Polynomial, render
import sympy
import bopytex.filters as filters import bopytex.filters as filters
formatter = logging.Formatter("%(name)s :: %(levelname)s :: %(message)s") formatter = logging.Formatter("%(name)s :: %(levelname)s :: %(message)s")
@ -24,13 +25,14 @@ logger.addHandler(steam_handler)
def setup(): def setup():
Expression.set_render("tex") render.set_render("tex")
logger.debug(f"Render for Expression is {Expression.RENDER}") logger.debug(f"Render for Expression is {render.render}")
mapytex_tools = { mapytex_tools = {
"Expression": Expression, "Expression": Expression,
"Integer": Integer, "Integer": Integer,
"Decimal": Decimal, "Decimal": Decimal,
# "Polynom": mapytex.Polynom, "Polynom": Polynomial,
"sympy": sympy,
# "Fraction": mapytex.Fraction, # "Fraction": mapytex.Fraction,
# "Equation": mapytex.Equation, # "Equation": mapytex.Equation,
# "random_str": mapytex.random_str, # "random_str": mapytex.random_str,
@ -157,7 +159,7 @@ def crazy_feed(*args, **kwrds):
def clean(directory): def clean(directory):
pytex.clean(directory) pytex.clean(directory, ["*.aux", "*.log", "*.out", "*.xsim", "*.tkzfonct.*"])
def texcompile(filename): def texcompile(filename):

View File

@ -3,7 +3,17 @@
import click import click
from .bopytex import produce_and_compile import logging
from pathlib import Path
from .bopytex import subject_metadatas, crazy_feed, pdfjoin, feed, clean, texcompile, setup, activate_printanswers
formatter = logging.Formatter("%(name)s :: %(levelname)s :: %(message)s")
steam_handler = logging.StreamHandler()
steam_handler.setLevel(logging.DEBUG)
steam_handler.setFormatter(formatter)
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logger.addHandler(steam_handler)
@click.command() @click.command()
@click.argument( @click.argument(
@ -76,7 +86,72 @@ def new(**options):
Feed the template (tpl_...) and then compile it with latex. Feed the template (tpl_...) and then compile it with latex.
""" """
produce_and_compile(options) setup()
logger.debug(f"CI parser gets {options}")
template = Path(options["template"]).name
directory = Path(options["template"]).parent
metadatas = subject_metadatas(options)
logger.debug(f"Metadata {metadatas}")
for meta in metadatas:
logger.debug(f"Feeding template toward {meta['texfile']}")
if options["crazy"]:
crazy_feed(
template=Path(meta["directory"]) / meta["template"],
data=meta,
output=meta["texfile"],
force=1,
)
else:
feed(
template=Path(meta["directory"]) / meta["template"],
data=meta,
output=meta["texfile"],
force=1,
)
assert(Path(meta["texfile"]).exists())
logger.debug(f"{meta['texfile']} fed")
if options["corr"]:
logger.debug(f"Building correction for {meta['texfile']}")
meta.update({
"corr_texfile": activate_printanswers(meta["texfile"]),
})
if not options["no_compile"]:
for prefix in ["", "corr_"]:
key = prefix + "texfile"
try:
meta[key]
except KeyError:
pass
else:
texcompile(meta[key])
meta.update({
prefix+'pdffile': meta[key].replace('tex', 'pdf')
})
if not options["no_join"]:
for prefix in ["", "corr_"]:
key = prefix + "pdffile"
try:
pdfs = [m[key] for m in metadatas]
except KeyError:
pass
else:
pdfjoin(
pdfs,
template.replace("tpl", prefix+"all").replace(".tex", ".pdf"),
directory,
rm_pdfs=1,
)
if not options["dirty"]:
clean(directory)
# produce_and_compile(options)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,18 +0,0 @@
% vim:ft=tex:
%
\documentclass[12pt]{article}
\begin{document}
\section{Ajouts de fractions}
Adding two fractions
\[
A = \frac{- 2}{4} + \frac{7}{8}
\]
Solution
\[
\frac{- 2}{4} + \frac{7}{8}=\frac{- 2 \times 2}{4 \times 2} + \frac{7}{8}=\frac{- 4}{8} + \frac{7}{8}=\frac{- 4 + 7}{8}=\frac{3}{8}
\]
\end{document}

View File

@ -1,18 +0,0 @@
% vim:ft=tex:
%
\documentclass[12pt]{article}
\begin{document}
\section{Ajouts de fractions}
Adding two fractions
\[
A = \frac{8}{9} + \frac{3}{63}
\]
Solution
\[
\frac{8}{9} + \frac{3}{63}=\frac{8 \times 7}{9 \times 7} + \frac{3}{63}=\frac{56}{63} + \frac{3}{63}=\frac{56 + 3}{63}=\frac{59}{63}
\]
\end{document}

Binary file not shown.

View File

@ -5,7 +5,7 @@ from setuptools import setup
setup( setup(
name='Bopytex', name='Bopytex',
version='0.1.1', version='0.1.2',
description='Command line tool for compiling latex with python command embedded', description='Command line tool for compiling latex with python command embedded',
author='Benjamin Bertrand', author='Benjamin Bertrand',
author_email='programming@opytex.org', author_email='programming@opytex.org',
@ -13,6 +13,7 @@ setup(
install_requires=[ install_requires=[
'mapytex', 'mapytex',
'mypytex', 'mypytex',
'click',
], ],
entry_points={ entry_points={
"console_scripts": ['bopytex=bopytex.script:new'] "console_scripts": ['bopytex=bopytex.script:new']

View File

@ -1,133 +0,0 @@
% vim:ft=tex:
%
\documentclass[12pt]{article}
\usepackage[utf8x]{inputenc}
\usepackage[francais]{babel}
\usepackage[T1]{fontenc}
\usepackage{amssymb}
\usepackage{amsmath}
\usepackage{amsfonts}
\title{
Snippets pour Opytex \\
Fractions
}
\author{
Benjamin Bertrand
}
\begin{document}
\maketitle
\section{Simplifications de fractions}
\begin{itemize}
\item Trouver le numérateur quand le dénominateur augmente
%
\begin{align*}
\dfrac{2}{6} = \dfrac{\ldots}{48}
\end{align*}
Solution
\begin{align*}
\dfrac{2}{6} = \dfrac{16}{48}
\end{align*}
\item Trouver le numérateur quand le dénominateur diminue
%
\begin{align*}
\dfrac{12}{9} = \dfrac{\cdots}{3}
\end{align*}
Solution
\begin{align*}
\dfrac{12}{9} = \dfrac{4}{3}
\end{align*}
Explications
\begin{align*}
\frac{ 12 }{ 9 }=\frac{ 4 \times 3 }{ 3 \times 3 }=\frac{ 4 }{ 3 }
\end{align*}
\end{itemize}
\section{Ajouts de fractions}
\begin{itemize}
\item Fraction avec le même dénominateur
\begin{align*}
A = \frac{ 1 }{ 4 } + \frac{ 5 }{ 4 }
\end{align*}
Solution
\begin{align*}
\frac{ 1 }{ 4 } + \frac{ 5 }{ 4 }=\frac{ 1 + 5 }{ 4 }=\frac{ 6 }{ 4 }=\frac{ 3 \times 2 }{ 2 \times 2 }=\frac{ 3 }{ 2 }
\end{align*}
\item Fraction avec un denominateur multiple de l'autre
\begin{align*}
A = \frac{ 10 }{ 7 } + \frac{ 3 }{ 49 }
\end{align*}
Solution
\begin{align*}
\frac{ 10 }{ 7 } + \frac{ 3 }{ 49 }=\frac{ 10 \times 7 }{ 7 \times 7 } + \frac{ 3 \times 1 }{ 49 \times 1 }=\frac{ 70 }{ 49 } + \frac{ 3 }{ 49 }=\frac{ 70 + 3 }{ 49 }=\frac{ 73 }{ 49 }
\end{align*}
\item Fraction avec des dénominateurs premiers entre eux
\begin{align*}
A = \frac{ 10 }{ 3 } + \frac{ 4 }{ 2 }
\end{align*}
Solution
\begin{align*}
\frac{ 10 }{ 3 } + \frac{ 4 }{ 2 }=\frac{ 10 \times 2 }{ 3 \times 2 } + \frac{ 4 \times 3 }{ 2 \times 3 }=\frac{ 20 }{ 6 } + \frac{ 12 }{ 6 }=\frac{ 20 + 12 }{ 6 }=\frac{ 32 }{ 6 }=\frac{ 16 \times 2 }{ 3 \times 2 }=\frac{ 16 }{ 3 }
\end{align*}
\item Une fraction et un entier
\begin{align*}
A = \frac{ 6 }{ 8 } + 9
\end{align*}
Solution
\begin{align*}
\frac{ 6 }{ 8 } + 9=\frac{ 6 \times 1 }{ 8 \times 1 } + \frac{ 9 \times 8 }{ 1 \times 8 }=\frac{ 6 }{ 8 } + \frac{ 72 }{ 8 }=\frac{ 6 + 72 }{ 8 }=\frac{ 78 }{ 8 }=\frac{ 39 \times 2 }{ 4 \times 2 }=\frac{ 39 }{ 4 }
\end{align*}
\item Une fraction et un entier
\begin{align*}
A = 2 + \frac{ 8 }{ 2 }
\end{align*}
Solution
\begin{align*}
2 + \frac{ 8 }{ 2 }=\frac{ 2 \times 2 }{ 1 \times 2 } + \frac{ 8 \times 1 }{ 2 \times 1 }=\frac{ 4 }{ 2 } + \frac{ 8 }{ 2 }=\frac{ 4 + 8 }{ 2 }=6
\end{align*}
\end{itemize}
\section{Multiplications de fractions}
\begin{itemize}
\item Une fraction et un entier
\begin{align*}
A = 5 \times \frac{ 7 }{ 8 }
\end{align*}
Solution
\begin{align*}
5 \times \frac{ 7 }{ 8 }=\frac{ 7 }{ 8 } \times 5=\frac{ 7 \times 5 }{ 8 }=\frac{ 35 }{ 8 }
\end{align*}
\item Fraction avec des dénominateurs quelconques
\begin{align*}
A = \frac{ 5 }{ 10 } \times \frac{ 4 }{ 7 }
\end{align*}
Solution
\begin{align*}
\frac{ 5 }{ 10 } \times \frac{ 4 }{ 7 }=\frac{ 4 }{ 7 } \times \frac{ 5 }{ 10 }=\frac{ 2 \times 2 \times 5 }{ 7 \times 5 \times 2 }=\frac{ 4 \times 5 }{ 7 \times 10 }=\frac{ 20 }{ 70 }=\frac{ 2 \times 10 }{ 7 \times 10 }=\frac{ 2 }{ 7 }
\end{align*}
\end{itemize}
\end{document}

Binary file not shown.

View File

@ -1,121 +0,0 @@
% vim:ft=tex:
%
\documentclass[12pt]{article}
\usepackage[utf8x]{inputenc}
\usepackage[french]{babel}
\usepackage[T1]{fontenc}
\usepackage{amssymb}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{graphicx}
\title{%
Snippets pour Opytex \\
Pythagore et Thalès
}
\author{%
Benjamin Bertrand
}
\begin{document}
\maketitle
\section{Pythagore}
\section{Thalès}
\section{Mélange des 2}
\subsection{Longueur du parcours}
% exo de geometrie comme au brevet blanc.
%- set AD, AC, DC = random_pythagore()
%- set tourACDA = AC+AD+DC
%- set AE, AF = round(tourACDA/2*random(), 1), round(tourACDA/2*random(), 1)
%- set EF = round(tourACDA - AE - AF - randint(20,40)*0.2, 1)
%- set tourAEFA = round(AE+EF+AF, 1)
%- set rapport = randint(2,5)
%- set AE1, AF1, EF1 = round(AE/rapport,2) , round(AF/rapport,2), round(EF/rapport,2)
%- set objectif = randint(floor(tourAEFA), tourACDA)
%- if objectif > 100
%- set unit = "m"
%- else
%- set unit = "km"
%- endif
Une commune souhaite aménager des parcours de santé sur son territoire. On fait deux propositions au conseil municipale, schématisés ci-dessous:
\begin{itemize}
\item Le parcours ACDA
\item Le parcours AEFA
\end{itemize}
Ils souhaitent faire un parcours dont la longueur s'approche le plus possible de \Var{objectif}\Var{unit}.
Peux-tu les aider à choisir le parcours? Justifie
\textbf{Attention: La figure proposée au conseil municipale n'est pas à l'échelle, mais les codages et les dimension données sont correctes.}
\begin{minipage}{0.6\textwidth}
\includegraphics[scale = 0.4]{./fig/parcours}
\end{minipage}
\begin{minipage}{0.4\textwidth}
\begin{itemize}
\item $AC = \Var{AC}\Var{unit}$
\item $CD = \Var{DC}\Var{unit}$
\item $AE' = \Var{AE1}\Var{unit}$
\item $AE = \Var{AE}\Var{unit}$
\item $AF = \Var{AF}\Var{unit}$
\item $E'F' = \Var{EF1}\Var{unit}$
\item $(E'F') // (EF)$
\item L'angle $\widehat{EAF}$ vaut $30^o$
\end{itemize}
\end{minipage}
\begin{solution}
\begin{itemize}
\item Parcours ACDA:
D'après la figure, on voit que le triangle $ACD$ est rectangle en $C$ donc d'après le théorème de Pythagore, on a
\begin{align*}
AD^2 &= AC^2 + DC^2 \\
AD^2 &= \Var{AC}^2 + \Var{DC}^2 \\
AD^2 &= \Var{AC**2} + \Var{DC**2} \\
AD^2 &= \Var{AC**2 + DC**2} \\
AD &= \sqrt{\Var{AC**2 + DC**2}} = \Var{AD}\Var{unit}
\end{align*}
Donc le parcours ACDA mesure
\begin{align*}
AD + AC + CD = \Var{AD} + \Var{AC} + \Var{DC} = \Var{tourACDA}\Var{unit}
\end{align*}
\item Parcours AEFA:
D'après les données, on sait que $(EF) // (E'F')$. On voit aussi que $A$, $E'$ et $E$ sont alignés. Il en est de même pour les points $A$, $F'$ et $F$. Donc d'après le théorème de Thalès
\begin{tabular}{|c|c|c|c|}
\hline
Triangle AEF & AE = \Var{AE} & AF = \Var{AF} & EF \\
\hline
Triangle AE'F' & AE' = \Var{AE1} & AF' & E'F' = \Var{EF1} \\
\hline
\end{tabular}
est un tableau de proportionnalité. Donc on peut faire un produit en croix pour calcul $EF$.
\begin{align*}
EF = \frac{E'F' \times AE}{AE'} = \frac{\Var{EF1} \times \Var{AE}}{\Var{AE1}} = \Var{EF} \Var{unit}
\end{align*}
Donc le parcours AEFA mesure
\begin{align*}
AF + AE + EF = \Var{AF} + \Var{AE} + \Var{EF} = \Var{tourAEFA}\Var{unit}
\end{align*}
\item Choix du parcours:
%- if abs(tourACDA - objectif) < abs(tourAEFA - objectif)
Il faudra choisir le tour $ACDA$ car sa longueur est plus proche de \Var{objectif}\Var{unit}.
%- else
Il faudra choisir le tour $AFEA$ car sa longueur est plus proche de \Var{objectif}\Var{unit}.
%- endif
\end{itemize}
\end{solution}
\end{document}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,96 +0,0 @@
% vim:ft=tex:
%
\documentclass[12pt]{article}
\usepackage[utf8x]{inputenc}
\usepackage[francais]{babel}
\usepackage[T1]{fontenc}
\usepackage{amssymb}
\usepackage{amsmath}
\usepackage{amsfonts}
\title{
Snippets pour Opytex \\
Fonctions
}
\author{
Benjamin Bertrand
}
\begin{document}
\maketitle
\section{Calculer des images}
\begin{enumerate}
%-set f = Expression.random("{a}*x^2 + {b}*x + {c}")
\item $\forall x \in \mathbb{R} \qquad f(x) = \Var{f}$
Solution:
\begin{align*}
f(0) &= \Var{f(0).explain() | join('=')} \\
f(1) &= \Var{f(1).explain() | join('=')} \\
f(2) &= \Var{f(2).explain() | join('=')} \\
f({10}) &= \Var{f(10).explain() | join('=')} \\
f({100}) &= \Var{f(100).explain() | join('=')}
\end{align*}
\end{enumerate}
\section{Résolution d'équation du 2nd degré}
%- macro solveEquation(P)
On commence par calculer le discriminant de $P(x) = \Var{P}$.
\begin{eqnarray*}
\Delta & = & b^2-4ac \\
\Var{P.delta.explain()|calculus(name="\\Delta")}
\end{eqnarray*}
\Block{if P.delta > 0}
comme $\Delta = \Var{P.delta} > 0$ donc $P$ a deux racines
\begin{eqnarray*}
x_1 & = & \frac{-b - \sqrt{\Delta}}{2a} = \frac{\Var{-P.b} - \sqrt{\Var{P.delta}}}{2 \times \Var{P.a}} = \Var{P.roots[0] } \\
x_2 & = & \frac{-b + \sqrt{\Delta}}{2a} = \frac{\Var{-P.b} + \sqrt{\Var{P.delta}}}{2 \times \Var{P.a}} = \Var{P.roots[1] }
\end{eqnarray*}
Les solutions de l'équation $\Var{P} = 0$ sont donc $\mathcal{S} = \left\{ \Var{P.roots[0]}; \Var{P.roots[1]} \right\}$
\Block{elif P.delta == 0}
Comme $\Delta = 0$ donc $P$ a une racine
\begin{eqnarray*}
x_1 = \frac{-b}{2a} = \frac{-\Var{P.b}}{2\times \Var{P.a}} = \Var{P.roots[0]} \\
\end{eqnarray*}
La solution de $\Var{P} = 0$ est donc $\mathcal{S} = \left\{ \Var{P.roots[0]}\right\}$
\Block{else}
Alors $\Delta = \Var{P.delta} < 0$ donc $P$ n'a pas de racine donc l'équation $\Var{P} = 0$ n'a pas de solution.
\Block{endif}
%- endmacro
\begin{enumerate}
%-set P = Expression.random("{a}*x^2 + {b}*x + {c}", ["b**2-4*a*c>0"])
\item Étude du polynôme $P$, $\forall x \in \mathbb{R} \quad P(x) = \Var{P}$
Solution:
\Var{solveEquation(P)}
%-set P = Expression.random("{a}*x^2 + {b}*x + {c}", ["b**2-4*a*c==0"])
\item Étude du polynôme $P$, $\forall x \in \mathbb{R} \quad P(x) = \Var{P}$
Solution:
\Var{solveEquation(P)}
%-set P = Expression.random("{a}*x^2 + {b}*x + {c}", ["b**2-4*a*c<0"])
\item Étude du polynôme $P$, $\forall x \in \mathbb{R} \quad P(x) = \Var{P}$
Solution:
\Var{solveEquation(P)}
\end{enumerate}
\end{document}

View File

@ -1,133 +0,0 @@
% vim:ft=tex:
%
\documentclass[12pt]{article}
\usepackage[utf8x]{inputenc}
\usepackage[francais]{babel}
\usepackage[T1]{fontenc}
\usepackage{amssymb}
\usepackage{amsmath}
\usepackage{amsfonts}
\title{
Snippets pour Opytex \\
Fractions
}
\author{
Benjamin Bertrand
}
\begin{document}
\maketitle
\section{Simplifications de fractions}
\begin{itemize}
\item Trouver le numérateur quand le dénominateur augmente
\Block{set a,b,ans,c = random_str("{a},{b},{a*c},{b*c}", conditions = ["{a} != {b}"], val_min = 2, val_max = 10).split(',')}%
\begin{align*}
\dfrac{\Var{a}}{\Var{b}} = \dfrac{\ldots}{\Var{c}}
\end{align*}
Solution
\begin{align*}
\dfrac{\Var{a}}{\Var{b}} = \dfrac{\Var{ans}}{\Var{c}}
\end{align*}
\item Trouver le numérateur quand le dénominateur diminue
\Block{set a,b,ans,c = random_str("{a*c},{b*c},{a},{b}", conditions = ["{a} != {b}"], val_min = 2, val_max = 10).split(',')}%
\begin{align*}
\dfrac{\Var{a}}{\Var{b}} = \dfrac{\cdots}{\Var{c}}
\end{align*}
Solution
\begin{align*}
\dfrac{\Var{a}}{\Var{b}} = \dfrac{\Var{ans}}{\Var{c}}
\end{align*}
Explications
\Block{set f = Expression(a + "/" +b)}
\begin{align*}
\Var{f.simplify().explain()|join('=')}
\end{align*}
\end{itemize}
\section{Ajouts de fractions}
\begin{itemize}
\item Fraction avec le même dénominateur
\Block{set e = Expression.random("{a} / {b} + {c} / {b}", ["{b} > 1"], val_min = 1)}
\begin{align*}
A = \Var{e}
\end{align*}
Solution
\begin{align*}
\Var{e.simplify().explain() | join('=')}
\end{align*}
\item Fraction avec un denominateur multiple de l'autre
\Block{set e = Expression.random("{a} / {b} + {c} / {b*d}", ["{b} > 1","{d} > 1"], val_min = 1)}
\begin{align*}
A = \Var{e}
\end{align*}
Solution
\begin{align*}
\Var{e.simplify().explain() | join('=')}
\end{align*}
\item Fraction avec des dénominateurs premiers entre eux
\Block{set e = Expression.random("{a} / {b} + {c} / {d}", ["{b} > 1","{d} > 1", "gcd({b},{d}) == 1"], val_min = 1)}
\begin{align*}
A = \Var{e}
\end{align*}
Solution
\begin{align*}
\Var{e.simplify().explain() | join('=')}
\end{align*}
\item Une fraction et un entier
\Block{set e = Expression.random("{a} / {b} + {c}", ["{b} > 1"], val_min = 1)}
\begin{align*}
A = \Var{e}
\end{align*}
Solution
\begin{align*}
\Var{e.simplify().explain() | join('=')}
\end{align*}
\item Une fraction et un entier
\Block{set e = Expression.random("{c} + {a} / {b}", ["{b} > 1"], val_min = 1)}
\begin{align*}
A = \Var{e}
\end{align*}
Solution
\begin{align*}
\Var{e.simplify().explain() | join('=')}
\end{align*}
\end{itemize}
\section{Multiplications de fractions}
\begin{itemize}
\item Une fraction et un entier
\Block{set e = Expression.random("{c} * {a} / {b}", ["{b} > 1"], val_min = 1)}
\begin{align*}
A = \Var{e}
\end{align*}
Solution
\begin{align*}
\Var{e.simplify().explain() | join('=')}
\end{align*}
\item Fraction avec des dénominateurs quelconques
\Block{set e = Expression.random("{a} / {b} * {c} / {d}", ["{b} > 1","{d} > 1"], val_min = 1)}
\begin{align*}
A = \Var{e}
\end{align*}
Solution
\begin{align*}
\Var{e.simplify().explain() | join('=')}
\end{align*}
\end{itemize}
\end{document}

View File

@ -1,87 +0,0 @@
% vim:ft=tex:
%
\documentclass[12pt]{article}
\usepackage[utf8x]{inputenc}
\usepackage[francais]{babel}
\usepackage[T1]{fontenc}
\usepackage{amssymb}
\usepackage{amsmath}
\usepackage{amsfonts}
\title{
Snippets pour Opytex \\
Suites
}
\author{
Benjamin Bertrand
}
\begin{document}
\maketitle
\section{Calculs de termes}
\begin{enumerate}
\item Calculer les termes $u_0$, $u_1$, $u_2$, $u_{10}$ et $u_{100}$ pour les suites suivantes
\begin{enumerate}
%-set u = Expression.random("{a}*n+{b}")
\item $\forall n \in \mathbb{N} \qquad u_n = \Var{u}$
Solution:
\begin{align*}
u_0 &= \Var{u(0).explain() | join('=')} \\
u_1 &= \Var{u(1).explain() | join('=')} \\
u_2 &= \Var{u(2).explain() | join('=')} \\
u_{10} &= \Var{u(10).explain() | join('=')} \\
u_{100} &= \Var{u(100).explain() | join('=')}
\end{align*}
%-set v = Expression.random("({a}*n+{b})/{c}", ["c>1"])
\item $\forall n \in \mathbb{N} \qquad v_n = \Var{v|replace("frac","dfrac")}$
Solution:
\begin{align*}
v_0 &= \Var{v(0).explain() | join('=')} \\
v_1 &= \Var{v(1).explain() | join('=')} \\
v_2 &= \Var{v(2).explain() | join('=')} \\
v_{10} &= \Var{v(10).explain() | join('=')} \\
v_{100} &= \Var{v(100).explain() | join('=')}
\end{align*}
%-set v = Expression.random("({a}*n+{b})/{c}", ["c>1"])
\item $\forall n \in \mathbb{N} \qquad v_n = \Var{v}$
Solution:
\begin{align*}
%- for j in [0, 1, 2, 10, 100]
v_{\Var{j}} &= \Var{v(j).explain() | join('=')} \\
%- endfor
\end{align*}
%-set f = Expression.random("{a}*x")
%-set v0 = randint(0, 10)
\item $\forall n \in \mathbb{N} \qquad v_{n+1} = \Var{f("v_n")} \mbox{ et } v_0 = \Var{v0}$
Solution:
\begin{align*}
v_0 &= \Var{v0} \\
%-set v = f(v0)
v_1 &= \Var{v.explain() | join('=')} \\
%-set v = f(v)
v_2 &= \Var{v.explain() | join('=')} \\
\end{align*}
Pour le terme 10, il faut calculer tous les autres avant!
\begin{align*}
%#- Trick to move around scoping rules
%#- https://stackoverflow.com/a/49699589
%- set v = namespace(val = v)
%- for i in range(8)
%- set v.val = f(v.val)
v_{\Var{i+3}} &= \Var{v.val.explain() | join('=')} \\
%- endfor
\end{align*}
\end{enumerate}
\end{enumerate}
\end{document}