source: pyromaths/trunk/fuentes/src/pyromaths/ex/lycee/TermesSuite.py @ 423

Last change on this file since 423 was 423, checked in by mabarracus, 4 years ago

add sources from pyromaths 15.10

File size: 28.8 KB
Line 
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3#
4# Pyromaths
5# Un programme en Python qui permet de créer des fiches d'exercices types de
6# mathématiques niveau collège ainsi que leur corrigé en LaTeX.
7# Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org)
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 2 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22#
23
24from pyromaths import ex
25import functools
26from math import sqrt
27import random
28from pyromaths.outils import Priorites3
29import textwrap
30from pyromaths.classes.Fractions import Fraction
31from pyromaths.classes.PolynomesCollege import Polynome, factoriser
32from pyromaths.classes.SquareRoot import SquareRoot
33from pyromaths.outils.Arithmetique import carrerise, pgcd, valeur_alea
34
35FRANCAIS_ORDINAL = {
36    1: u"premier",
37    2: u"deuxième",
38    3: u"troisième",
39    4: u"quatrième",
40    5: u"cinquième",
41    6: u"sixième",
42    7: u"septième",
43    }
44FRANCAIS_INVERSE = {
45    2: u"à la moitié du",
46    3: u"au tiers du",
47    4: u"au quart du",
48    5: u"au cinquième du",
49    6: u"au sixième du",
50    7: u"au septième du",
51    8: u"au huitième du",
52    9: u"au neuvième du",
53    10: u"au dixième du",
54    }
55FRANCAIS_MULTIPLE = {
56    2: u"au double du",
57    3: u"au triple du",
58    4: u"au quadruple du",
59    5: u"à cinq fois le",
60    6: u"à six fois le",
61    7: u"à sept fois le",
62    8: u"à huit fois le",
63    9: u"à neuf fois le",
64    10: u"à dix fois le",
65    }
66NOTATIONS = [
67    ur"u",
68    ur"\left(u_n\right)",
69    ur"\left(u_n\right)_{n\in\mathbb{N}}",
70    ]
71
72def signe(nombre):
73    if nombre > 0:
74        return 1
75    if nombre < 0:
76        return -1
77    raise ValueError
78
79class Fraction:
80    def __init__(self, numerateur, denominateur, signe=1):
81        self.signe = signe
82        self.numerateur = numerateur
83        self.denominateur = denominateur
84
85    def latex(self):
86        if self.denominateur == 1:
87            return str(self.numerateur)
88        else:
89            if self.signe == 1:
90                signe = ""
91            else:
92                signe = "-"
93            return ur"{}\frac{{ {} }}{{ {} }}".format(
94                    signe,
95                    self.numerateur,
96                    self.denominateur,
97                    )
98
99    def simplifie(self):
100        if self.numerateur % self.denominateur == 0:
101            return Entier(self.signe * self.numerateur / self.denominateur)
102        diviseur = pgcd(self.numerateur, self.denominateur)
103        return Fraction(
104                self.numerateur/diviseur,
105                self.denominateur/diviseur,
106                self.signe,
107                )
108
109    def __float__(self):
110        return float(self.signe * self.numerateur / self.denominateur)
111
112
113
114@functools.total_ordering
115class Entier:
116    def __init__(self, valeur):
117        self.valeur = valeur
118
119    def __int__(self):
120        return self.valeur
121
122    def __neg__(self):
123        return self.__class__(- self.valeur)
124
125    def __lt__(self, other):
126        if isinstance(other, int):
127            return self.valeur < other
128        elif isinstance(other, Entier):
129            return self.valeur < other.valeur
130        else:
131            raise TypeError()
132
133    def __eq__(self, other):
134        if isinstance(other, int):
135            return self.valeur == other
136
137        elif isinstance(other, Entier):
138            return self.valeur == other.valeur
139        else:
140            raise TypeError()
141
142    def latex(self, signe="-"):
143        if signe == "+":
144            if self.valeur >= 0:
145                return "+" + str(self.valeur)
146            else:
147                return "-" + str(abs(self.valeur))
148        else:
149            if self.valeur >= 0:
150                return str(self.valeur)
151            else:
152                return "-" + str(abs(self.valeur))
153
154    def __float__(self):
155        return float(self.valeur)
156
157FRACTIONS = [
158        Fraction(2, 1),
159        Fraction(3, 1),
160        Fraction(4, 1),
161        Fraction(5, 1),
162        Fraction(10, 1),
163        Fraction(1, 2),
164        Fraction(1, 3),
165        Fraction(1, 4),
166        Fraction(1, 5),
167        Fraction(1, 10),
168        Fraction(2, 3),
169        Fraction(1, 4),
170        Fraction(3, 4),
171        Fraction(2, 5),
172        Fraction(3, 5),
173        Fraction(4, 5),
174        ]
175
176class Fonction:
177
178    def calcul(self, argument):
179        raise NotImplementedError()
180
181    def resultat(self, variable):
182        raise NotImplementedError()
183
184    def expression(self, variable):
185        raise NotImplementedError()
186
187class Lineaire(Fonction):
188
189    def __init__(self):
190        self.coeff = random.choice(FRACTIONS)
191
192    def expression(self, variable):
193        return ur"{coeff}{variable}".format(
194            coeff=self.coeff.latex(),
195            variable=variable,
196            )
197
198    def calcul(self, argument):
199        if isinstance(argument, Entier):
200            if float(argument) < 0:
201                arg = ur"\left( {} \right)".format(argument.latex())
202            else:
203                arg = argument.latex()
204            yield self.expression(ur"\times " + arg)
205            if isinstance(self.coeff.simplifie(), Fraction):
206                yield Fraction(
207                            self.coeff.numerateur * argument.valeur,
208                            self.coeff.denominateur,
209                            ).latex()
210                if pgcd(self.coeff.numerateur * argument.valeur, self.coeff.denominateur) != 1:
211                    yield self.resultat(argument).latex()
212            else:
213                yield self.resultat(argument).latex()
214        else:
215            yield self.expression(ur"\times " + argument.latex())
216            yield Fraction(
217                self.coeff.numerateur * argument.numerateur,
218                self.coeff.denominateur * argument.denominateur,
219                ).latex()
220            if pgcd(
221                self.coeff.numerateur * argument.numerateur,
222                self.coeff.denominateur * argument.denominateur,
223                ) != 1:
224                yield self.resultat(argument).latex()
225
226    def resultat(self, variable):
227        if isinstance(variable, Entier):
228            variable = Fraction(variable.valeur, 1)
229        return Fraction(
230            self.coeff.numerateur * variable.numerateur,
231            self.coeff.denominateur * variable.denominateur,
232            ).simplifie()
233
234class Affine(Fonction):
235
236    def __init__(self):
237        self.coeff = random.choice(FRACTIONS)
238        ordonnee = random.randint(1, 10)
239        if random.randint(1, 2) == 1:
240            ordonnee = -ordonnee
241        self.ordonnee = Entier(ordonnee)
242
243    def expression(self, variable):
244        return ur"{coeff}{variable}{ordonnee}".format(
245            coeff=self.coeff.latex(),
246            ordonnee=self.ordonnee.latex("+"),
247            variable=variable,
248            )
249
250    def calcul(self, argument):
251        if float(argument) < 0:
252            arg = ur"\left( {} \right)".format(argument.latex())
253        else:
254            arg = argument.latex()
255        yield self.expression(ur"\times " + arg)
256        if isinstance(argument, Entier):
257            if isinstance(self.coeff.simplifie(), Fraction):
258                yield ur"{fraction} {signe} \frac{{ {ordonnee} \times {denom} }}{{ {denom} }}".format(
259                        fraction=Fraction(
260                            self.coeff.numerateur * argument.valeur,
261                            self.coeff.denominateur,
262                            ).latex(),
263                        ordonnee=abs(self.ordonnee.valeur),
264                        denom=self.coeff.denominateur,
265                        signe=Entier(self.coeff.denominateur * self.ordonnee.valeur).latex("+")[0],
266                        )
267                yield ur"\frac{{ {gauche} {droite} }}{{ {denom} }}".format(
268                        gauche=self.coeff.numerateur * argument.valeur,
269                        droite=Entier(self.coeff.denominateur * self.ordonnee.valeur).latex("+"),
270                        denom=self.coeff.denominateur,
271                        )
272        else:
273            yield ur"{} + \frac{{ {} \times {} }}{{ {} }}".format(
274                Fraction(
275                    self.coeff.numerateur * argument.numerateur,
276                    self.coeff.denominateur * argument.denominateur,
277                    ).latex(),
278                self.ordonnee.valeur,
279                self.coeff.denominateur * argument.denominateur,
280                self.coeff.denominateur * argument.denominateur,
281                )
282            yield ur"\frac{{ {} {} }}{{ {} }}".format(
283                self.coeff.numerateur * argument.numerateur,
284                Entier(self.ordonnee.valeur * self.coeff.denominateur * argument.denominateur).latex("+"),
285                self.coeff.denominateur * argument.denominateur,
286                )
287        yield self.resultat(argument).latex()
288
289    def resultat(self, variable):
290        if isinstance(variable, Entier):
291            variable = Fraction(variable.valeur, 1)
292        return Fraction(
293            self.coeff.numerateur * variable.numerateur + self.ordonnee.valeur * self.coeff.denominateur * variable.denominateur,
294            self.coeff.denominateur * variable.denominateur,
295            ).simplifie()
296
297class FractionProduit(Fonction):
298
299    def __init__(self):
300        self.numerateur = Entier(random.randint(2, 10))
301        self.denominateur = Entier(random.randint(2, 10))
302
303    def expression(self, variable):
304        return ur"\frac{{ {numerateur}^{variable} }}{{ {denominateur}{variable} }}".format(
305                numerateur=self.numerateur.latex("-"),
306                denominateur=self.denominateur.latex("-"),
307                variable=variable,
308            )
309
310    def calcul(self, argument):
311        if argument.valeur < 0:
312            arg2 = ur"\left( {} \right)".format(argument.latex())
313        else:
314            arg2 = argument.latex()
315        yield ur"\frac{{ {numerateur}^{{ {argument} }}}}{{ {denominateur}\times{arg2} }}".format(
316                numerateur=self.numerateur.latex(),
317                denominateur=self.denominateur.latex(),
318                argument=argument.latex(),
319                arg2=arg2,
320            )
321        yield ur"\frac{{ {} }}{{ {} }}".format(
322                self.numerateur.valeur ** argument.valeur,
323                self.denominateur.valeur * argument.valeur,
324                )
325        if pgcd(
326                self.numerateur.valeur ** argument.valeur,
327                self.denominateur.valeur * argument.valeur,
328                ) != 1:
329            yield self.resultat(argument).latex()
330
331    def resultat(self, argument):
332        return Fraction(
333                self.numerateur.valeur ** argument.valeur,
334                self.denominateur.valeur * argument.valeur,
335                ).simplifie()
336
337class Trinome(Fonction):
338
339    def __init__(self):
340        coef = [0]*3
341        for i in [0, 1, 2]:
342            coef[i] = random.randint(2, 5)
343            if random.randint(0,1) == 0:
344                coef[i] = -coef[i]
345        self.coef = [Entier(i) for i in coef]
346
347    def expression(self, variable):
348        return ur"{coef[2]}{variable}^2{coef[1]}{variable}{coef[0]}".format(
349            coef=[self.coef[0].latex("+"), self.coef[1].latex("+"), self.coef[2].latex("-")],
350            variable=variable,
351            )
352
353    def calcul(self, argument):
354        if argument < 0:
355            texargument = ur"\left{{ {variable} }}".format(argument.latex())
356        else:
357            texargument = argument.latex()
358        yield ur"{coef[2]}\times{argument}^2{coef[1]}\times{argument}{coef[0]}".format(
359            coef=[self.coef[0].latex("+"), self.coef[1].latex("+"), self.coef[2].latex("-")],
360            argument=texargument,
361            )
362        yield ur"{}{}{}".format(
363            Entier(self.coef[2].valeur * argument.valeur**2).latex(),
364            Entier(self.coef[1].valeur * argument.valeur).latex("+"),
365            Entier(self.coef[0].valeur).latex("+")
366            )
367        yield Entier(
368            (self.coef[2].valeur * argument.valeur**2) +
369            (self.coef[1].valeur * argument.valeur) +
370            (self.coef[0].valeur)
371            ).latex()
372
373    def resultat(self, argument):
374        return Entier(self.coef[2].valeur * argument.valeur**2 + self.coef[1].valeur * argument.valeur + self.coef[0].valeur)
375
376
377class IdentiteTranslatee(Fonction):
378
379    def __init__(self):
380        ordonnee = random.randint(1, 10)
381        if random.randint(1, 2) == 1:
382            ordonnee = -ordonnee
383        self.ordonnee = Entier(ordonnee)
384
385    def expression(self, variable):
386        return ur"{variable}{ordonnee}".format(
387            variable=variable,
388            ordonnee=self.ordonnee.latex("+"),
389            )
390
391    def calcul(self, argument):
392        yield self.expression(argument.latex())
393        yield self.resultat(argument).latex()
394
395    def resultat(self, variable):
396        return Entier(variable.valeur + self.ordonnee.valeur)
397
398class FrancaisGeometrique(Fonction):
399
400    def __init__(self):
401        if random.randint(1, 2) == 1:
402            self.raison = Fraction(1, random.randint(2, 10))
403        else:
404            self.raison = Entier(random.randint(2, 10))
405
406    @property
407    def francais(self):
408        if isinstance(self.raison, Fraction):
409            return u"{} précédent".format(FRANCAIS_INVERSE[self.raison.denominateur])
410        else:
411            return u"{} précédent".format(FRANCAIS_MULTIPLE[self.raison.valeur])
412
413    def expression(self, variable):
414        # L'argument est du code LaTeX
415        return ur"{} {}".format(self.raison.latex(), variable)
416
417    def calcul(self, argument):
418        yield ur"{} \times {}".format(self.raison.latex(), argument.latex())
419        resultat = self.resultat(argument).latex()
420        if isinstance(resultat, Entier):
421            yield self.resultat(argument).latex()
422        else:
423            if isinstance(argument, Entier):
424                argument = Fraction(argument.valeur, 1)
425            raison = self.raison
426            if isinstance(raison, Entier):
427                raison = Fraction(raison.valeur, 1)
428            numerateur = argument.numerateur * raison.numerateur
429            denominateur = raison.denominateur * argument.denominateur
430            yield ur"\frac{{ {} }}{{ {} }}".format(numerateur, denominateur)
431            if numerateur % denominateur == 0:
432                yield Entier(numerateur / denominateur).latex()
433                return
434
435            diviseur = pgcd(numerateur, denominateur)
436            if diviseur == 1:
437                return
438
439            yield Fraction(numerateur/diviseur, denominateur/diviseur).latex()
440
441    def resultat(self, argument):
442        if isinstance(argument, Entier) and isinstance(self.raison, Entier):
443            return Entier(argument.valeur * self.raison.valeur)
444        else:
445            if isinstance(argument, Entier):
446                argument = Fraction(argument.valeur, 1)
447            if isinstance(self.raison, Entier):
448                raison = Fraction(self.raison.valeur, 1)
449            else:
450                raison = self.raison
451            numerateur = argument.numerateur * raison.numerateur
452            denominateur = raison.denominateur * argument.denominateur
453            if numerateur % denominateur == 0:
454                return Entier(numerateur / denominateur)
455            diviseur = pgcd(numerateur, denominateur)
456            return Fraction(numerateur/diviseur, denominateur/diviseur)
457
458class FrancaisArithmetique(Fonction):
459
460    def __init__(self):
461        self.raison = random.randint(1, 10)
462        if random.randint(1, 2) == 1:
463            self.raison = -self.raison
464
465    @property
466    def francais(self):
467        if self.raison > 0:
468            return u"au terme précédent auquel on ajoute {}".format(self.raison)
469        else:
470            return u"au terme précédent auquel on soustrait {}".format(-self.raison)
471
472    def expression(self, variable):
473        # L'argument est du code LaTeX
474        return ur"{} {}".format(variable, Entier(self.raison).latex("+"))
475
476    def calcul(self, argument):
477        yield self.expression(argument.latex())
478        yield self.resultat(argument).latex()
479
480    def resultat(self, argument):
481        return Entier(argument.valeur + self.raison)
482
483class FrancaisOppose(Fonction):
484
485    @property
486    def francais(self):
487        return u"à l'opposé du précédent"
488
489    def expression(self, variable):
490        # L'argument est du code LaTeX
491        if variable < 0:
492            return ur"-\left({}\right)".format(variable)
493        else:
494            return ur"-{}".format(variable)
495
496    def calcul(self, argument):
497        yield Entier(-argument.valeur).latex("-")
498
499    def resultat(self, argument):
500        if not isinstance(argument, Entier):
501            raise TypeError("Argument must be an instance of `Entier`.")
502        return - argument
503
504class FrancaisInverse(Fonction):
505
506    @property
507    def francais(self):
508        return u"à l'inverse du précédent"
509
510    def expression(self, variable):
511        # L'argument est du code LaTeX
512        return ur"\frac{{1}}{{ {} }}".format(variable)
513
514    def calcul(self, argument):
515        yield self.expression(argument.latex())
516        if isinstance(argument, Entier) and argument > 0:
517            pass
518        elif isinstance(argument, Entier) and argument < 0:
519            yield ur"-{}".format(self.expression((-argument).latex()))
520        elif isinstance(argument, Fraction):
521            yield self.resultat(argument).latex()
522        else:
523            raise TypeError("Argument must be an instance of `Entier` or `Fraction`.")
524
525    def resultat(self, argument):
526        if isinstance(argument, Fraction):
527            if argument.numerateur == 1:
528                return Entier(argument.denominateur * argument.signe)
529            else:
530                return Fraction(
531                    abs(argument.denominateur),
532                    abs(argument.numerateur),
533                    signe(argument.numerateur * argument.denominateur),
534                    )
535        elif isinstance(argument, Entier):
536            return Fraction(1, abs(argument.valeur), signe(argument.valeur))
537        raise TypeError("Argument must be an instance of `Entier` or `Fraction`.")
538
539
540class Question(object):
541
542    def __init__(self, indice0):
543        self.indice0 = indice0
544        if self.indice0 == 0:
545            self.notation = NOTATIONS[random.randint(0, 2)]
546        else:
547            self.notation = NOTATIONS[random.randint(0, 1)]
548
549class Francais(Question):
550
551    def __init__(self, indice0):
552        super(Francais, self).__init__(indice0)
553        self.terme0 = Entier(random.randint(-10, 10))
554        self.fonction = random.choice([
555            FrancaisGeometrique,
556            FrancaisArithmetique,
557            FrancaisOppose,
558            FrancaisInverse,
559            ])()
560
561    @property
562    def latex_params(self):
563        return {
564            'indice0': self.indice0,
565            'terme0': self.terme0.latex("-"),
566            'suivant': self.fonction.francais,
567            'notation': self.notation,
568            }
569
570class General(Question):
571
572    def __init__(self, indice0):
573        super(General, self).__init__(indice0)
574        self.fonction = random.choice([
575            FractionProduit,
576            Trinome,
577            Affine,
578            Lineaire,
579            IdentiteTranslatee,
580            ])()
581
582    @property
583    def latex_params(self):
584        return {
585            'indice0': self.indice0,
586            'fonction': self.fonction.expression(ur"n"),
587            'notation': self.notation,
588            }
589
590class Recursif(Question):
591
592    def __init__(self, indice0):
593        super(Recursif, self).__init__(indice0)
594        self.terme0 = Entier(random.randint(-10, 10))
595        self.fonction = random.choice([
596            Affine,
597            IdentiteTranslatee,
598            Lineaire,
599            ])()
600
601    @property
602    def latex_params(self):
603        return {
604            'indice0': self.indice0,
605            'terme0': self.terme0.latex("-"),
606            'fonction': self.fonction.expression(ur"u_n"),
607            'notation': self.notation,
608            }
609
610class TermesDUneSuite(ex.TexExercise):
611
612    description = u"Termes d'une suite"
613    level = u"1.1èreS"
614
615    def __init__(self):
616        # * `self.rang[0]` désigne l'ordinal du premier terme demandé (pour la
617        #   première question de chacune des trois suites) ;
618        # * `self.rang[1]` et `self.rang[2]` sont les rangs demandés pour les
619        #   deux questions suivantes dans chacune des trois suites.
620        self.rang = [random.randint(2, 7)] + random.sample(range(3, 7), 2)
621
622        self.questions = [
623                Francais(random.randint(0, min(self.rang[1:])-1)),
624                General(random.randint(0, min(self.rang[1:])-1)),
625                Recursif(random.randint(0, min(self.rang[1:])-1)),
626                ]
627
628    def tex_statement(self):
629        exo = [r'\exercice']
630        exo.append(ur'Pour chacune des suites $u$ suivantes, calculer :')
631        exo.append(ur' (a) le {} terme ;'.format(FRANCAIS_ORDINAL[self.rang[0]]))
632        exo.append(ur' (b) le terme de rang {} ;'.format(self.rang[1]))
633        exo.append(ur' (c) $u_{}$.'.format(self.rang[2]))
634
635        exo.append(ur'\begin{enumerate}')
636        exo.append(ur'  \item ${notation}$ est une suite de premier terme $u_{indice0}={terme0}$, et dont chaque terme (sauf le premier) est égal {suivant}.'.format(**self.questions[0].latex_params))
637        exo.append(ur'  \item ${notation}$ est la suite définie pour $n\geq{indice0}$ par : $u_n={fonction}$.'.format(**self.questions[1].latex_params))
638        exo.append(textwrap.dedent(ur"""
639            \item ${notation}$ est la suite définie pour $n\geq{indice0}$ par :
640                \[\left\{{\begin{{array}}{{l}}
641                  u_{indice0}={terme0}\\
642                  \text{{Pour tout $n\geq{indice0}$ : }} u_{{n+1}}={fonction}.
643              \end{{array}}\right.\]
644              """).format(**self.questions[2].latex_params))
645        exo.append(ur'\end{enumerate}')
646        return exo
647
648    def tex_answer(self):
649        exo = [r'\exercice*']
650        exo.append(ur'\begin{enumerate}')
651        # Question 0
652        exo.append(ur"  \item Selon l'énoncé, le premier terme de ${notation}$ est $u_{indice0}={terme0}$. Puisque chaque terme (sauf le premier) est égal {suivant}, on a :".format(**self.questions[0].latex_params))
653        termes = dict([(self.questions[0].indice0, self.questions[0].terme0)])
654        calcul_termes = []
655        for indice in xrange(self.questions[0].indice0, max(self.rang[0] + self.questions[0].indice0 - 1, self.rang[1], self.rang[2])):
656            calcul = ur"$u_{indice}={fonction}".format(
657                indice=indice+1,
658                fonction=self.questions[0].fonction.expression("u_{}".format(indice)),
659                )
660            for etape in self.questions[0].fonction.calcul(termes[indice]):
661                calcul += " =" + etape
662            calcul += "$"
663            termes[indice+1] = self.questions[0].fonction.resultat(termes[indice])
664            calcul_termes.append(calcul)
665        exo.append(" ; ".join(calcul_termes) + ".")
666        exo.append(ur'\begin{enumerate}')
667        exo.append(ur' \item Calcul du {} terme :'.format(FRANCAIS_ORDINAL[self.rang[0]]))
668        enumeration = []
669        for indice in range(0, self.rang[0]):
670            enumeration.append(u"le {ordinal} terme est $u_{indice}$".format(ordinal=FRANCAIS_ORDINAL[indice+1], indice=self.questions[0].indice0+indice))
671        exo.append(" ; ".join(enumeration) + ".")
672        exo.append(ur"Le terme demandé est donc : $u_{}={}$.".format(self.rang[0] + self.questions[0].indice0 - 1, termes[self.rang[0] + self.questions[0].indice0 - 1].latex()))
673        exo.append(ur'\item Le terme de rang {indice} est : $u_{indice}={valeur}$.'.format(indice=self.rang[1], valeur=termes[self.rang[1]].latex()))
674        exo.append(ur'\item Nous avons calculé que : $u_{indice}={valeur}$.'.format(indice=self.rang[2], valeur=termes[self.rang[2]].latex()))
675        exo.append(ur'\end{enumerate}')
676
677        # Question 1
678        exo.append(ur'  \item La suite ${notation}$ est définie pour $n\geq{indice0}$ par : $u_n={fonction}$.'.format(**self.questions[1].latex_params))
679        exo.append(ur"Elle est donc définie par son terme général : pour calculer un terme de rang $n$, on peut calculer directement l'image de $n$ par la suite.")
680        exo.append(ur'\begin{enumerate}')
681        exo.append(ur' \item Calcul du {} terme :'.format(FRANCAIS_ORDINAL[self.rang[0]]))
682        enumeration = []
683        for indice in range(0, self.rang[0]):
684            enumeration.append(u"le {ordinal} terme est $u_{indice}$".format(ordinal=FRANCAIS_ORDINAL[indice+1], indice=self.questions[1].indice0+indice))
685        exo.append(" ; ".join(enumeration) + ".")
686        exo.append(ur"Le terme demandé est donc : $u_{}=".format(self.rang[0] + self.questions[1].indice0 - 1))
687        calcul = []
688        for etape in self.questions[1].fonction.calcul(Entier(self.rang[0] + self.questions[1].indice0 - 1)):
689            calcul.append(etape)
690        exo.append(u" = ".join(calcul) + ur"$.")
691        exo.append(ur"La solution est $u_{{ {} }}={}$.".format(self.rang[0] + self.questions[1].indice0 - 1, self.questions[1].fonction.resultat(Entier(self.rang[0] + self.questions[1].indice0 - 1)).latex()))
692        exo.append(ur"\item Le terme de rang {rang} est $u_{{ {rang} }}$.".format(rang=self.rang[1]))
693        if self.rang[0] + self.questions[1].indice0 - 1 == self.rang[1]:
694            exo.append(ur"Ce terme a déjà été calculé, et $u_{{ {} }}={}$.".format(self.rang[1], self.questions[1].fonction.resultat(Entier(self.rang[1])).latex()))
695        else:
696            calcul = []
697            for etape in self.questions[1].fonction.calcul(Entier(self.rang[1])):
698                calcul.append(etape)
699            exo.append(ur"Le terme demandé est donc : $u_{{ {} }}=".format(self.rang[1]) + " = ".join(calcul) + ur"$.")
700            exo.append(ur"La solution est donc  : $u_{{ {} }}={}$.".format(self.rang[1], self.questions[1].fonction.resultat(Entier(self.rang[1])).latex()))
701        exo.append(ur"\item")
702        if self.rang[0] + self.questions[1].indice0 - 1 == self.rang[2]:
703            exo.append(ur"Ce terme a déjà été calculé, et $u_{{ {} }}={}$.".format(self.rang[2], self.questions[1].fonction.resultat(Entier(self.rang[2])).latex()))
704        else:
705            calcul = []
706            for etape in self.questions[1].fonction.calcul(Entier(self.rang[2])):
707                calcul.append(etape)
708            exo.append(ur"On a : $u_{{ {} }}=".format(self.rang[2]) + " = ".join(calcul) + ur"$.")
709            exo.append(ur"La solution est donc  : $u_{{ {} }}={}$.".format(self.rang[2], self.questions[1].fonction.resultat(Entier(self.rang[2])).latex()))
710        exo.append(ur'\end{enumerate}')
711
712        # Question 2
713        exo.append(textwrap.dedent(ur"""
714            \item La suite ${notation}$ est définie par récurrence, pour $n\geq{indice0}$, par :
715                \[\left\{{\begin{{array}}{{l}}
716                  u_{indice0}={terme0}\\
717                  \text{{Pour tout $n\geq{indice0}$ : }} u_{{n+1}}={fonction}.
718              \end{{array}}\right.\]
719              """).format(**self.questions[2].latex_params))
720        termes = dict([(self.questions[2].indice0, self.questions[2].terme0)])
721        calcul_termes = []
722        for indice in xrange(self.questions[2].indice0, max(self.rang[0] + self.questions[2].indice0 - 1, self.rang[1], self.rang[2])):
723            calcul = ur"u_{indice} &= {fonction}".format(
724                indice=indice+1,
725                fonction=self.questions[2].fonction.expression("u_{}".format(indice)),
726                )
727            for etape in self.questions[2].fonction.calcul(termes[indice]):
728                calcul += " =" + etape
729            termes[indice+1] = self.questions[2].fonction.resultat(termes[indice])
730            calcul_termes.append(calcul)
731        exo.append(ur"\begin{align*}")
732        exo.append(ur" \\".join(calcul_termes))
733        exo.append(ur"\end{align*}")
734        exo.append(ur'\begin{enumerate}')
735        exo.append(ur' \item Calcul du {} terme :'.format(FRANCAIS_ORDINAL[self.rang[0]]))
736        enumeration = []
737        for indice in range(0, self.rang[0]):
738            enumeration.append(u"le {ordinal} terme est $u_{indice}$".format(ordinal=FRANCAIS_ORDINAL[indice+1], indice=self.questions[2].indice0+indice))
739        exo.append(" ; ".join(enumeration) + ".")
740        exo.append(ur"Le terme demandé est donc : $u_{}={}$.".format(self.rang[0] + self.questions[2].indice0 - 1, termes[self.rang[0] + self.questions[2].indice0 - 1].latex()))
741        exo.append(ur'\item Le terme de rang {indice} est : $u_{indice}={valeur}$.'.format(indice=self.rang[1], valeur=termes[self.rang[1]].latex()))
742        exo.append(ur'\item Nous avons calculé que : $u_{indice}={valeur}$.'.format(indice=self.rang[2], valeur=termes[self.rang[2]].latex()))
743        exo.append(ur'\end{enumerate}')
744
745        exo.append(ur'\end{enumerate}')
746        return exo
Note: See TracBrowser for help on using the repository browser.