source: pyromaths/trunk/fuentes/src/pyromaths/ex/sixiemes/decimaux.py @ 1653

Last change on this file since 1653 was 1653, checked in by Juanma, 3 years ago

WIP Pyromaths i18n

File size: 34.9 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
24import random
25import os
26from pyromaths.outils import Affichage, Arithmetique
27#===============================================================================
28# Écrire un nombre en lettres ou en chiffres
29#===============================================================================
30
31
32def NombreEnLettres(n, France=True):
33    unite = {
34        1: "un",
35        2: 'deux',
36        3: 'trois',
37        4: 'quatre',
38        5: 'cinq',
39        6: 'six',
40        7: 'sept',
41        8: 'huit',
42        9: 'neuf',
43        10: 'dix',
44        11: 'onze',
45        12: 'douze',
46        13: 'treize',
47        14: 'quatorze',
48        15: 'quinze',
49        16: 'seize',
50        17: 'dix-sept',
51        18: 'dix-huit',
52        19: 'dix-neuf',
53        }
54    dizaineF = {2: 'vingt', 3: 'trente', 4: 'quarante', 5: 'cinquante',
55                6: 'soixante', 7: "", 8: 'quatre-vingt', 9: ""}
56    dizaineB = {2: 'vingt', 3: 'trente', 4: 'quarante', 5: 'cinquante',
57                6: 'soixante', 7: 'septante', 8: 'octante', 9: 'nonante'}
58    coefs = {0: 'cent', 1: 'mille', 2: 'million', 3: 'milliard'}
59    result = ""
60
61    # Cas particulier de zéro
62    if n == 0:
63        result = u'zéro'
64    else:
65        coef = 0
66
67        while n > 0:
68
69        # Récupération de l'unité du bloc de trois chiffres en cours
70
71            u = n % 10
72            n = n // 10
73
74        # Récupération de la dizaine du bloc de trois chiffres en cours
75
76            d = n % 10
77            n = n // 10
78        # Traitement des dizaines
79
80            temp = ""
81
82        # Passage sur la dizaine inférieure pour 10 à 19
83        # et pour 70-79 90-99 dans le cas de la France
84
85            if d == 1 or (d == 7 or d == 9) and France:
86                d = d - 1
87                u = u + 10
88            if d > 1:
89                if France:
90                    if n:
91                        temp = '-' + dizaineF[d]
92                    else:
93                        temp = dizaineF[d]
94
95                    # Ajout du cas particulier de 'et' entre la dizaine et 1
96
97                    if d < 8 and (u == 1 or u == 11):
98                        temp = temp + '-et'
99                else:
100                    if n:
101                        temp = '-' + dizaineB[d]
102                    else:
103                        temp = dizaineB[d]
104
105                    # Ajout du cas particulier de 'et' entre la dizaine et 1
106
107                    if u == 1:
108                        temp = temp + '-et'
109
110        # ajout du texte de l'unité
111
112            if u > 0 and (d or n):
113                temp = temp + '-' + unite[u]
114            elif u > 0:
115                temp = unite[u]
116
117        # ajout du 's' à Quatre-vingt si rien ne suit
118        # if (result == '') and (d == 8) and (u == 0) and France : result = 's'
119
120            if d == 8 and u == 0 and France:
121                temp = temp + 's'
122            result = temp + result
123
124
125            # Récupération de la centaine du bloc de trois chiffres en cours
126
127            c = n % 10
128            n = n // 10
129            if c > 0:
130                temp = ""
131                if c > 1 and n:
132                    temp = '-' + unite[c]
133                elif c > 1:
134                    temp = unite[c]
135                if c == 1 and not n:
136                    temp = coefs[0]
137                else:
138                    temp = temp + '-' + coefs[0]
139
140                # Traitement du cas particulier du 's' à cent si rien ne suit
141
142                if result == "" and c > 1:
143                    result = 's'
144                result = temp + result
145
146            # Traitement du prochain groupe de 3 chiffres
147
148            if n > 0:
149                coef = coef + 1
150                i = n % 1000
151                if i > 1 and coef > 1:
152                    result = 's' + result
153
154                # Traitement du cas particulier 'mille' ( non pas 'un mille' )
155
156                if i == 1 and coef == 1:
157                    n = n - 1
158                    result = coefs[coef] + result
159                elif i > 0:
160
161                    result = '-' + coefs[coef] + result
162    return result
163
164def NombreEnLettres_es(n):
165    unite = {
166        1: 'uno',
167        2: 'dos',
168        3: 'tres',
169        4: 'cuatro',
170        5: 'cinco',
171        6: 'seis',
172        7: 'siete',
173        8: 'ocho',
174        9: 'nueve',
175        10: 'diez',
176        11: 'once',
177        12: 'doce',
178        13: 'trece',
179        14: 'catorce',
180        15: 'quince',
181        16: u'dieciséis',
182        17: 'diecisiete',
183        18: 'dieciocho',
184        19: 'diecinueve',
185        20: 'veinte',
186        21: 'veintiun',             #Está bien así, NO CORREGIR
187        22: u'veintidós',
188        23: u'veintitrés',
189        24: 'veinticuatro',
190        25: 'veinticinco',
191        26: u'veintiséis',
192        27: 'veintisiete',
193        28: 'veintiocho',
194        29: 'veintinueve',
195        }
196    dizaineE = {3: 'treinta', 4: 'cuarenta', 5: 'cincuenta',
197                6: 'sesenta', 7: 'setenta', 8: 'ochenta', 9: 'noventa'}
198    coefs = {0: 'cien', 1: 'mil', 2: 'mill', 3:'mil'}
199    coefc = {0: 'un', 1: 'ciento', 2: 'dosci', 3: 'tresci', 4:'cuatroci', 5:'quini',
200                6: 'seisci', 7: 'seteci', 8: 'ochoci', 9: 'noveci'}
201    result = ""
202   
203    #Cas particulier de zéro
204    if n == 0:
205        result = u'cero'
206    else:
207        coef = 0
208
209        while n > 0:
210
211        # Récupération de l'unité du bloc de trois chiffres en cours
212
213            u = n % 10
214            n = n // 10
215
216        # Récupération de la dizaine du bloc de trois chiffres en cours
217
218            d = n % 10
219            n = n // 10
220        # Traitement des dizaines
221
222            temp = ""
223
224        # Passage sur la dizaine inférieure pour 10 à 19
225        # et pour 70-79 90-99 dans le cas de la France
226
227            if d == 1:                  # Escribe los nº del 10 al 19 de la tabla
228                d = d - 1
229                u = u + 10
230            if d == 2:                  # Escribe los nº del 20 al 21 de la tabla
231                d = d - 1
232                u = u + 20
233            if d > 2:
234
235            # Ajout du cas particulier de 'et' entre la dizaine et 1
236
237                    if n:               # Escribe el resto del 30 al 99
238                        temp = ' ' + dizaineE[d]    # Añade espacio si es > 100
239                    else:
240                        temp = dizaineE[d]
241
242        # ajout du texte de l'unité
243
244            if u > 0 and d > 2:                         # Añade "y" de los nº entre 30 a 99
245                if u == 1 and coef > 0:                 # Usa "un" en lugar de "uno"
246                    temp = temp + ' y ' + coefc[0]
247                else:
248                    temp = temp + ' y ' + unite[u]
249            elif u > 0 and n:                           # Añade espacio si es > 100
250                if u == 21 and coef == 0: # Usa "veintiuno" en lugar de "veintiun" si <1000
251                    temp = temp + ' ' + unite[u] + 'o'
252                elif u == 1 and (coef > 0 and coef < 4):    # Usa "un" en lugar de "uno"
253                    if coef == 3:
254                        temp = temp                         # Usa "mil millones" en lugar de "un mil"
255                    else:
256                        temp = ' ' + coefc[0]
257                else:
258                    temp = temp + ' ' + unite[u]
259            elif u == 21 and d == 1 and coef == 0:  # Usa "veintiuno" cuando es 21
260                temp = unite[u] + 'o'
261            elif u == 1 and d == 0 and coef > 0:  # Usa "un" son numeros > 1000
262                temp = coefc[0]
263            elif u > 0:
264                temp = unite[u]
265
266            result = temp + result
267
268
269        # Récupération de la centaine du bloc de trois chiffres en cours
270
271            c = n % 10
272            n = n // 10
273            if c > 0:
274                temp = ""
275                if c == 1 and not d and not u:  # Usa "cien" en lugar de "un cien"
276                    temp = coefs[0]
277                elif c == 1:                      # Usa "ciento" para >100
278                    temp = coefc[1]
279                else:                           # Compone los nº > 200
280                    temp = coefc[c] + 'entos'
281
282        # Traitement du cas particulier du 's' à cent si rien ne suit
283
284                if n > 0 :                      # Añade espacio si es > 1000
285                    result = ' ' + temp + result
286                else:
287                    result = temp + result
288
289        # Traitement du prochain groupe de 3 chiffres
290
291            if n > 0:
292                coef = coef + 1
293                i = n % 1000
294
295          # Traitement du cas particulier 'mille' ( non pas 'un mille' )
296
297                if coef == 1 and i==1:        # No añade espacio en "mil"
298                    n = n - 1
299                    if n == 0:
300                        result = coefs[coef] + result
301                    else:
302                        result = ' ' + coefs[coef] + result
303                elif coef == 2:      # Usa "millones" en lugar de "millón"
304                    if i == 1 and n == 1:
305                        result = ' ' + coefs[coef] + u'ón' + result
306                    else:
307                        result = ' ' + coefs[coef] + 'ones' + result
308                elif i == 1 and coef == 3:      # No añade espacio en "mil millones"
309                    result = coefs[coef] + result
310                elif i > 0:
311                    result = ' ' + coefs[coef] + result
312
313    return result
314
315
316
317def nombreATrouver():
318    """a contient la liste des nombres à créer où il peut ne pas y avoir de
319    centaines, de centaines de milliers, d'unités ou de milliers"""
320
321    a = [random.randrange(100) + random.randrange(1000) * 10 ** 3,
322         random.randrange(1000) + random.randrange(100) * 10 ** 3,
323         random.randrange(1000) * 10 ** 3, random.randrange(1000)]
324    (lnb, liste) = ([], [])
325    for i in range(4):
326        lnb.append(random.randrange(1, 1000) * 10 ** 6 + a[i])
327    for i in range(4):
328        n = a[i]
329        if n % 1000:  # il y a des unités dans le nombre
330            e = random.randrange(1, 4)
331            lnb.append(n * 10 ** (-e))
332        else:
333            e = random.randrange(4, 7)
334            lnb.append(n * 10 ** (-e))
335    for i in range(8):
336        liste.append(lnb.pop(random.randrange(len(lnb))))
337    return liste
338
339def EcritNombreDecimal(n):
340    txt = ""
341    if n != int(n):
342        # n n'est pas un nombre entier
343        (e, d) = str(n).split('.')
344        (e, d) = (int(e), int(d))
345    else:
346        (e, d) = (int(n), 0)
347    if not d:
348        txt = NombreEnLettres(e)
349    elif e:
350        txt = NombreEnLettres(e)
351    if d:
352        partieDec = [u" dixième", u" centième", u" millième"]
353        if txt.rfind("un") == len(txt) - 2:
354
355        # le texte se finit par un. On l'accorde en genre avec unité
356
357            txt = txt + "e"
358        if e == 1:
359            txt = txt + u' unité et '
360        if e > 1:
361            txt = txt + u' unités et '
362        txt = txt + NombreEnLettres(d) + partieDec[len(str(n).split('.')[1]) - 
363                1]
364        if d > 1:
365            txt = txt + 's'
366    return txt
367
368def EcritNombreDecimal_es(n):
369    txt = ""
370    if n != int(n):
371        #n n'est pas un nombre entier
372        (e, d) = str(n).split('.')
373        (e, d) = (int(e), int(d))
374    else:
375        (e, d) = (int(n), 0)
376    if not d:
377        txt = NombreEnLettres_es(e)
378    elif e:
379        txt = NombreEnLettres_es(e)
380    if d:
381        partieDec = [u" décima", u" centésima", u" milésima"]
382        if e == 1:
383            txt = txt + u' unidad con '
384        if e > 1:
385            txt = txt + u' unidades con '
386        txt = txt + NombreEnLettres_es(d) + partieDec[len(str(n).split('.')[1]) -
387                1]
388        if d > 1:
389            txt = txt + 's'
390        txt = txt.replace("uno", "una")     # Cambio a femenino para decimales
391        txt = txt.replace("un ", "una ")    # Cambio a femenino para decimales
392        txt = txt.replace("tos", "tas")    # Cambio a femenino para decimales
393    return txt
394
395
396
397def EcritEnChiffre(exo, cor,lang=""):
398    lnb = nombreATrouver()
399    for i in range(len(lnb)):
400        exo.append("\\item " + eval('EcritNombreDecimal'+lang+'(lnb[i])') +
401                 " : \\dotfill")
402        cor.append("\\item " + eval('EcritNombreDecimal'+lang+'(lnb[i])') +
403                   " : ")
404        cor.append(Affichage.decimaux(lnb[i], 0) + '')
405
406
407def EcritEnLettre(exo, cor,lang=""):
408    lnb = nombreATrouver()
409    for i in range(8):
410        exo.append("\\item " + Affichage.decimaux(lnb[i], 0) + 
411                 " : \\dotfill")
412        cor.append("\\item " + Affichage.decimaux(lnb[i], 0) + 
413                " : ")
414        cor.append(eval('EcritNombreDecimal'+lang+'(lnb[i])') + '')
415
416
417def EcrireNombreLettre():
418
419    langue = os.getenv('LANG')
420
421    if langue == "fr" or langue == "":
422        lang = ""
423    else:
424        lang = "_" + langue[0:2]
425        try:
426            eval('EcritNombreDecimal'+lang+'(1)')
427        except NameError:
428            lang = ""
429
430
431    exo = ["\\exercice", "\\begin{enumerate}",
432            _(u'\\item Écrire en chiffres les nombres suivants.'),
433            '\\begin{enumerate}']
434    cor = ["\\exercice*", "\\begin{enumerate}",
435            _(u'\\item Écrire en chiffres les nombres suivants.'),
436            '\\begin{enumerate}']
437
438    EcritEnChiffre(exo, cor,lang)
439
440    exo.append('\\end{enumerate}')
441    exo.append(_(u'\\item Écrire en lettres les nombres suivants (sans utiliser le mot ``virgule").'))
442    exo.append('\\begin{enumerate}')
443    cor.append('\\end{enumerate}')
444    cor.append(_(u'\\item Écrire en lettres les nombres suivants (sans utiliser le mot ``virgule").'))
445    cor.append('\\begin{enumerate}')
446
447    EcritEnLettre(exo, cor,lang)
448
449    exo.append('\\end{enumerate}')
450    exo.append('\\end{enumerate}')
451    cor.append('\\end{enumerate}')
452    cor.append('\\end{enumerate}')
453    return (exo, cor)
454
455EcrireNombreLettre.description = _(u'Écrire un nombre décimal')
456
457def NombreEnLettres_ca(n):
458    unite = {1: 'un',2: 'dos',3: 'tres',4: 'quatre',5: 'cinc',6: 'sis',7: 'set',
459             8: 'huit',9: 'nou',10: 'deu',11: 'onze',12: 'dotze',13: 'tretze',
460             14: 'catorze',15: 'quinze',16: 'setze',17: u'dèsset',18: 'dihuit',19: u'dènou'}
461
462    dizaineE = {2:'vint',3: 'trenta', 4: 'quaranta', 5: 'cinquanta',
463                6: 'seixanta', 7: 'setanta', 8: 'huitanta', 9: 'noranta'}
464
465    suffix_num = {0:[ ['',''] , [u'milió','milions'] , [u'bilió','bilions'] ],1:'mil'}
466
467    result = ""
468    loops = 0
469  # Cas particulier de zéro
470    if n == 0:
471        result = u'zero'
472    else:
473        while n > 0 :
474
475            c = n % 1000 // 100
476            d = n % 100 // 10
477            u = n % 10
478            n = n // 1000
479            aux_dec = ( d * 10 ) + u
480            aux_string = ''
481            aux_centesima = c*100+d*10+u
482            if c == 1 :
483                aux_string = 'cent'
484            elif c > 1:
485                aux_string = unite[c] + '-cents'
486
487            if aux_dec > 0 :
488                if aux_dec < 20:
489                    if not (aux_dec == 1 and (loops % 2) == 1):
490                        aux_string += ' ' + unite[aux_dec]
491                else:
492                    aux_string += ' ' + dizaineE[d]
493                    if u != 0:
494                        if d == 2:
495                            aux_string += '-i'
496                        aux_string += '-' + unite[u]
497            if aux_centesima != 0:
498                if ( loops % 2 ) == 0:
499
500                    if aux_centesima > 1:
501                        aux_string += ' ' + suffix_num[0][loops//2][1]
502                    else:
503                        aux_string += ' ' + suffix_num[1]
504
505            result = aux_string.strip() + ' ' + result
506            loops += 1
507    return result
508
509def EcritNombreDecimal_ca(n):
510    txt = ""
511    if n != int(n):
512        #n n'est pas un nombre entier
513        (e, d) = str(n).split('.')
514        (e, d) = (int(e), int(d))
515    else:
516        (e, d) = (int(n), 0)
517    if not d:
518        txt = NombreEnLettres_ca(e)
519    elif e:
520        txt = NombreEnLettres_ca(e)
521    if d:
522        partieDec = [u"dècima", u"centèsima", u"mil·lèsima"]
523        if e == 1:
524            txt = txt + u'unitat amb '
525        if e > 1:
526            txt = txt + u'unitats amb '
527        txt = txt + NombreEnLettres_ca(d) + partieDec[len(str(n).split('.')[1]) - 1]
528        if d > 1:
529            txt = txt[:len(txt)-1] + 'es'
530        #txt = txt.replace("un", "una")     # Cambio a femenino para decimales
531        txt = txt.replace("-un ", "-una ")    # Cambio a femenino para decimales
532        txt = txt.replace("un ", "una ")    # Cambio a femenino para decimales
533        txt = txt.replace("cents", "centes")    # Cambio a femenino para decimales
534    return txt
535
536
537
538#===============================================================================
539# Conversions
540#===============================================================================
541
542units = ["L", "m", "g"]
543division = ["k", "h", "da", "", "d", "c", "m"]
544
545# paramétrage des flèches : mofifie le paramétrage par défaut de PSTricks  s'il n'est pas limité par un environnement ou {groupe}
546# # nodesepA = -1.5mm  : décale le départ de la flèche
547# # linewidth = 0.6pt  : épaisseur de la flèches
548# # linestyle = dotted : style pointillé
549# # vref = -0.8mm      : décale la flèche vers le bas, sous les chiffres
550PSSET_FLECHE = '\\psset{nodesepA = -1.5mm, linewidth = 0.6pt, linestyle = dotted, vref = -0.8mm}'
551
552
553def valeurs_units():
554    """
555    renvoie les valeurs pour les conversions d'unités
556    """
557
558    a = Arithmetique.valeur_alea(101, 999)
559    p = random.randrange(-2, 0)
560    unit = random.randrange(3)
561    if unit:
562        # mètres ou grammes, on peut utiliser les k
563        imax = 7
564    else:
565        # Litres, donc pas de kL
566        imax = 6
567
568    div0 = random.randrange(imax + p)
569
570    while 1:
571        div1 = random.randrange(imax)
572        if div0 != div1:
573            break
574
575    if not unit:  # Litres, donc pas de kL donc on décale d'un rang
576        div0, div1 = div0 + 1, div1 + 1
577
578    return (a, p, unit, div0, div1)
579        # 101< a <999 ex a = 245
580        # p = {-2,-1} donne 2,45 ou 24,5
581        # unit = {0, 1, 2} => {L, m, g}
582        # div0 unité 0
583        # div1 unité converti
584
585def tex_units():
586    """
587    Écrit l'exercice sur les conversions d'unités et le corrigé au format
588    LaTeX
589    @param exo: fichier exercices
590    @param cor: fichier corrige
591    """
592
593    exo = ["\\exercice", _(u'Effectuer les conversions suivantes :'),
594            '\\begin{multicols}{3}\\noindent', '\\begin{enumerate}']
595    cor = ["\\exercice*",
596            # paramétrage des flèches, ce paramétrage est limité à l'exercice
597            # et ne modifie pas le paramétrage PSTricks du document car sa portée est limité par le groupe ouvert par "{"
598           "{",
599            PSSET_FLECHE,
600           _(u'Effectuer les conversions suivantes :'),
601            '\\begin{multicols}{2}\\noindent', '\\begin{enumerate}']
602
603    # Construit les 6 questions de l'exercice
604    for i in range(6):
605        (a, p, unit, div0, div1) = valeurs_units()
606        if unit:
607            u = tuple([units[unit] for i in range(7)])
608        else:
609            u = tuple([units[unit] for i in range(6)])
610        nb0 = Affichage.decimaux(a * 10 ** p, 0)
611        nb1 = Affichage.decimaux(a * 10 ** ((p + div1) - div0),
612                0)
613        exo.append("\\item %s~%s%s=\dotfill~%s%s" % (nb0, division[div0],
614                 units[unit], division[div1], units[unit]))
615        cor.append("\\item %s~%s%s=%s~%s%s\\par" % (nb0, division[div0],
616                 units[unit], nb1, division[div1], units[unit]))
617        nblist = [nb0[i] for i in range(len(nb0))]
618        if nblist.count(','):
619            chf_unite = nblist.index(',') - 1
620            nblist.pop(chf_unite + 1)
621        else:
622            chf_unite = len(nblist) - 1
623
624        tex_tableau(cor, div0, div1, u, nblist, chf_unite)
625
626        cor.append("\\end{tabular}")
627        cor.append("\\ncline{->}{virg0}{virg1}")
628
629    exo.append('\\end{enumerate}')
630    exo.append('\\end{multicols}')
631    cor.append('\\end{enumerate}')
632    cor.append('\\end{multicols}')
633    # ferme le groupe limitant la portée de PSSET_FLECHE
634    cor.append('{')
635    return (exo, cor)
636
637tex_units.description = _(u'Conversions unités')
638
639
640def tex_tableau(cor, div0, div1, u, nblist, chf_unite):
641    """tableau de conversion pour les unités simples : L, g ou m"""
642
643    # Si len(u) == 6, on a des Litres, on ne doit pas avoir la colonne kL
644    if len(u) == 6:
645        cor.append("\\begin{tabular}{c|c|c|c|c|c}")
646        cor.append("h%s & da%s & %s & d%s & c%s & m%s \\\\ \\hline" % u)
647        # décale d'une colonne pour supprimer kL
648        delta = 1
649        div0 = div0 - 1
650        div1 = div1 - 1
651
652    else:
653        cor.append("\\begin{tabular}{c|c|c|c|c|c|c}")
654        cor.append("k%s & h%s & da%s & %s & d%s & c%s & m%s \\\\ \\hline" % u)
655        # ne supprime pas le kg, km
656        delta = 0
657    for dummy in range(-div0 + chf_unite):
658        tmp = nblist.pop(0)
659        nblist[0] = tmp + nblist[0]
660
661    for dummy in range(div0 - chf_unite):
662        nblist.insert(0, '0')
663
664
665    for dummy in range(-len(u) + len(nblist)):
666        tmp = nblist.pop(7)
667        nblist[6] = nblist[6] + tmp
668
669    # les zéros à droites des chiffres significatifs
670    for dummy in range(len(u) - len(nblist)):
671        nblist.append('0')
672
673    # place les \nodes et la virgule dans le tableau
674    nblist[div0] = "%s\\Rnode{virg0}{\\ }" % (nblist[div0])
675    nblist[div1] = "{%s\\Rnode{virg1}{\\textcolor{red}{ \\LARGE ,}}}" % (nblist[div1])
676
677    # ajoute au tabular la ligne avec 6 ou 7 colonnes
678    cor.append(("%s " + ("& %s"*(6 - delta))) % tuple(nblist))
679
680
681
682def exo_conversion(exposant):
683    """construit l'exercice de conversion d'unité d'aire ou de volume
684    exposant 2 pour m²
685    exposant 3 pour m³"""
686
687    exo = ["\\exercice", _(u'Effectuer les conversions suivantes :'),
688            '\\begin{multicols}{3}\\noindent', '\\begin{enumerate}']
689    cor = ["\\exercice*",
690            # la portée de \psset est par le group ouvert par "{"
691            "{",
692            PSSET_FLECHE,
693            '\\def\\virgule{\\textcolor{red}{ \\LARGE ,}}',
694            _(u'Effectuer les conversions suivantes :'),
695            '\\begin{multicols}{2}\\noindent', '\\begin{enumerate}']
696
697    # ajoute le ² ou ³ si nécessaire
698    str_exposant = (_(u"^%s") % (exposant)) * (exposant > 1)
699
700    u = tuple([division[i] + "m%s" % str_exposant for i in range(7)])
701    entete_tableau = ((" \\multicolumn{%s}{c|}" % exposant + "{$\\rm %s$} &") * 6 + "\\multicolumn{%s}{c}" % exposant + "{$\\rm %s$}") % u
702    ligne_tab = []
703
704    for i in range(6):
705        # imprime la correction et sauvegarde la ligne et la flèche pour le tableau imprimé ensuite
706        ligne_tab += tex_conversion(exo, cor, exposant, u) + ["\\ncline{->}{virg0}{virg1} \\\\"]
707
708    # ferme la correction et l'énoncé
709    cor.append('\\end{enumerate}')
710    cor.append('\\end{multicols}')
711    exo.append('\\end{enumerate}')
712    exo.append('\\end{multicols}')
713
714    # impression du tableau et des lignes sauvegardées précédemment
715    cor.append("\\begin{tabular}{*{%s}{p{3.5mm}|}p{3.5mm}}" % (exposant * 7 - 1))
716    cor.append(entete_tableau + "\\\\ \\hline")
717    # ajoute les lignes affichant les conversions
718    cor += ligne_tab
719    cor.append("\\end{tabular}")
720    # ferme le groupe dans lequel PSSET_FLECHE portait
721    cor.append("}")
722    # C'est fini
723    return (exo, cor)
724
725def exo_conversion_2d():
726    return exo_conversion(2)
727exo_conversion_2d.description = _(u"Conversions unités d'aires")
728
729def exo_conversion_3d():
730    return exo_conversion(3)
731exo_conversion_3d.description = _(u"Conversions unités de volumes")
732
733
734def tex_conversion(exo, cor, exposant, u):
735    """Écrit une question sur les conversions d'unités d'aires ou de volume
736    et le corrigé au format LaTeX
737    @param exo: fichier exercices
738    @param cor: fichier corrige
739    exposant = 2 ou 3 pour les aires ou les volumes
740    """
741
742    a = random.randint(101, 999)
743    p = random.randint(-2, -1)
744    while True:
745        (div0, div1) = (random.randrange(6), random.randrange(7),)
746        # Pas de mm³ par ce que ça sort du tableau
747        if (div0 - div1) in [-2, -1, 1, 2]:
748            # pas trop loin car ça fait de très longs nombres
749            break
750    nb0 = a * 10 ** p
751    nb1 = nb0 * 10 ** (exposant * (div1 - div0))
752
753    exo.append("\\item $\\unit[%s]{%s}=\\unit[\\dotfill]{%s}$" % 
754            (Affichage.decimaux(nb0), u[div0], u[div1]))
755    cor.append("\\item $\\unit[%s]{%s}=\\unit[%s]{%s}$\\vspace{1ex}\\par" % 
756            (Affichage.decimaux(nb0), u[div0],
757                Affichage.decimaux(nb1), u[div1]))
758
759    return tex_tableau_conversion(div0, div1, nb0, u, exposant)
760
761
762def tex_tableau_conversion(div0, div1, nb0, u, exposant):
763    nb_dict = nbre_to_dict(nb0, div0, div1, exposant)
764    nblist = [str(nb_dict.get(i, "")) for i in range(7 * exposant)]
765    nblist[exposant * (div0 + 1) - 1] = "%s\\Rnode{virg0}{\\ }" % nb_dict.get(exposant * (div0 + 1) - 1, "0")
766    nblist[exposant * (div1 + 1) - 1] = "{%s\\Rnode{virg1}{\\virgule}}" % nb_dict.get(exposant * (div1 + 1) - 1, "0")
767    return [("%s " + "& %s"*(7 * exposant - 1)) % tuple(nblist)]
768
769
770def nbre_to_dict(nbre , div0, div1, exposant):
771    # exposant peut être 2 ou 3 pour les m² ou les m³
772    nbre = int(round(nbre * 100))
773    nb_dict = {}
774    for i in range(min(exposant * (div0 + 1), exposant * (div1 + 1)) - 1, max(exposant * (div0 + 1), exposant * (div1 + 1))):
775            nb_dict[i] = "\\textcolor{red}{0}"
776    curseur = 1 + exposant * (div0 + 1)
777    while nbre % 10 == 0:
778        nbre = nbre / 10
779        curseur -= 1
780    while nbre > 0:
781        chiffre = nbre % 10
782        nbre = (nbre - chiffre) / 10
783        nb_dict[curseur] = "\\textcolor{blue}{%s}" % chiffre
784        curseur -= 1
785    return nb_dict
786
787
788#===============================================================================
789# Placer une virgule
790#===============================================================================
791
792valeurs = ["milliers", "centaines", "dizaines", u"unités",
793           _(u"dixièmes"), _(u"centièmes"), _(u"millièmes")]
794
795
796def valeurs_decimaux():
797    """
798    Choisit les valeurs
799    """
800
801    nb = 0
802    chiffres = [1, 2, 3, 4, 5, 6, 7, 8, 9]
803    for i in range(6):
804        nb = nb + chiffres.pop(random.randrange(len(chiffres))) * 10 ** \
805            i
806    return nb
807
808
809def tex_place_virgule(exo, cor):
810    """
811    Écrit un exercices demandant de placer une virgule dans un nombre.
812    @param exo: fichier exerices
813    @param cor:fichier corrigé
814    """
815
816    valeurs_index = [0, 1, 2, 3, 4, 5, 6]
817    nb = valeurs_decimaux()
818    exo.append(_(u"Placer une virgule (en ajoutant éventuellement des zéros) dans\
819            le nombre %s de telle sorte que :" % nb))
820    exo.append('\\begin{enumerate}')
821    cor.append(_(u"Placer une virgule (en ajoutant éventuellement des zéros) dans\
822            le nombre %s de telle sorte que :" % nb))
823    cor.append('\\begin{enumerate}')
824    for i in range(6):
825        dec = [str(nb)[i] for i in range(len(str(nb)))]
826        index_dec = random.randrange(6)
827        index_valeurs = valeurs_index.pop(random.randrange(len(valeurs_index)))
828        exo.append(_(u"\\item le chiffre %s soit le chiffre des %s : ") \
829                 % (dec[index_dec], valeurs[index_valeurs]))
830        cor.append(_(u"\\item le chiffre %s soit le chiffre des %s : ") \
831                 % (dec[index_dec], valeurs[index_valeurs]))
832        resultat = ecrit_nombre_decimal(dec, (index_dec + 4) - 
833                index_valeurs)
834        exo.append('\\dotfill')
835        cor.append(Affichage.decimaux(resultat, 0) + '')
836    exo.append('\\end{enumerate}')
837    cor.append('\\end{enumerate}')
838
839
840def ecrit_nombre_decimal(dec, index):
841    """
842    Renvoie une chaine de caractère représentant le nombre dec avec la
843    virgule à la place index.
844    Ajoute les zéros nécessaires.
845    @param dec: décomposition d'un nombre entier
846    @param index: place de la virgule dans la liste dec
847    """
848
849    if index < 1:
850        dec.insert(0, '0')
851        dec.insert(1, '.')
852        for i in range(-index):
853            dec.insert(2, '0')
854    elif index < len(dec):
855        dec.insert(index, '.')
856    else:
857        for i in range(index - len(dec)):
858            dec.append('0')
859    strnb = ""
860    for i in range(len(dec)):
861        strnb = strnb + dec[i]
862    return strnb
863
864
865def PlaceVirgule():
866    exo = ["\\exercice"]
867    cor = ["\\exercice*"]
868
869    tex_place_virgule(exo, cor)
870    return (exo, cor)
871
872PlaceVirgule.description = _(u'Placer une virgule')
873
874
875#===============================================================================
876#    Écriture fractionnaire
877#===============================================================================
878
879
880def valeurs_frac():
881    n1 = random.randrange(11, 10000)
882    p1 = random.randrange(1, 4)
883    return (n1, p1)
884
885
886def choix_trou_frac(exo, cor, n1, p1):
887    i = random.randrange(3)
888    p2 = random.randrange(2)  # sert à compliquer un peu l'exercice
889    if i > 1:
890        exo.append('\\item $\\cfrac{%s}{%s}=\\ldots$' % 
891                (Affichage.decimaux(n1 * 10 ** p2),
892                    Affichage.decimaux(10 ** (p1 + p2))))
893        cor.append('\\item $\\cfrac{%s}{%s}=\\mathbf{%s}$' % 
894                (Affichage.decimaux(n1 * 10 ** p2),
895                    Affichage.decimaux(10 ** (p1 + p2)),
896                    Affichage.decimaux(n1 * 10 ** (-p1), 1)))
897    elif i > 0:
898        exo.append('\\item $\\cfrac{%s}{\ldots}=%s$' % 
899                (Affichage.decimaux(n1 * 10 ** p2),
900        Affichage.decimaux(n1 * 10 ** (-p1), 1)))
901        cor.append('\\item $\\cfrac{%s}{\\mathbf{%s}}=%s$' % 
902                (Affichage.decimaux(n1 * 10 ** p2),
903        Affichage.decimaux(10 ** (p1 + p2)), \
904                Affichage.decimaux(n1 * 10 ** (-p1), 1)))
905    else:
906        exo.append('\\item $\\cfrac{\ldots}{%s}=%s$' % 
907                (Affichage.decimaux(10 ** (p1 + p2)),
908        Affichage.decimaux(n1 * 10 ** (-p1), 1)))
909        cor.append('\\item $\\cfrac{\\mathbf{%s}}{%s}=%s$' % 
910                (Affichage.decimaux(n1 * 10 ** p2),
911                    Affichage.decimaux(10 ** (p1 + p2)),
912                    Affichage.decimaux(n1 * 10 ** (-p1), 1)))
913
914def tex_frac(exo, cor):
915    for dummy in range(6):
916        (nombre, puissance) = valeurs_frac()
917        choix_trou_frac(exo, cor, nombre, puissance)
918
919
920def EcritureFractionnaire():
921    exo = ["\\exercice", _(u"Compléter :"), '\\begin{multicols}{3}\\noindent',
922            '\\begin{enumerate}']
923    cor = ["\\exercice*", _(u"Compléter :"), '\\begin{multicols}{3}\\noindent',
924            '\\begin{enumerate}']
925
926    tex_frac(exo, cor)
927
928    exo.append('\\end{enumerate}')
929    exo.append('\\end{multicols}')
930    cor.append('\\end{enumerate}')
931    cor.append('\\end{multicols}')
932    return (exo, cor)
933
934EcritureFractionnaire.description = _(u'Écriture fractionnaire ou décimale')
935
936
937#===============================================================================
938#    Décomposition des nombres décimaux
939#===============================================================================
940
941
942def valeurs_dec():
943    lpuissances = [3, 2, 1, 0, -1, -2, -3]
944    p = []
945    v = []
946    for dummy in range(3):
947        p.append(lpuissances.pop(random.randrange(len(lpuissances))))
948        v.append(random.randrange(1, 10))
949    return (v, p)
950
951
952def tex_decomposition(v, p):
953    exo, cor = [], []
954    for i in range(3):
955        if p[i] < 0:
956            exo.append('%s\\times \\cfrac{1}{%s}' % (v[i],
957                Affichage.decimaux(10 ** (-p[i]), 1)))
958            cor.append('%s\\times \\cfrac{1}{%s}' % (v[i],
959                Affichage.decimaux(10 ** (-p[i]), 1)))
960        else:
961            exo.append('%s\\times %s' % (v[i], Affichage.decimaux(10 ** 
962                     p[i], 1)))
963            cor.append('%s\\times %s' % (v[i], Affichage.decimaux(10 ** 
964                     p[i], 1)))
965        if i < 2:
966            exo.append('+')
967            cor.append('+')
968        else:
969            exo.append('=')
970            cor.append('=')
971    exo.append('\\dotfill$')
972    cor.append('%s$' % Affichage.decimaux(v[0] * 10 ** p[0] + 
973             v[1] * 10 ** p[1] + v[2] * 10 ** p[2], 1))
974    return " ".join(exo), " ".join(cor)
975
976
977def tex_dec(exo, cor):
978    for dummy in range(6):
979        txt = '\\item $'
980        (chiffres, puissances) = valeurs_dec()
981        txt_exo, txt_cor = tex_decomposition(chiffres, puissances)
982        exo.append(txt + txt_exo)
983        cor.append(txt + txt_cor)
984
985def Decomposition():
986    exo = ["\\exercice", _(u"Compléter avec un nombre décimal :"),
987            '\\begin{multicols}{2}\\noindent', '\\begin{enumerate}']
988    cor = ["\\exercice*", _(u"Compléter avec un nombre décimal :"),
989            '\\begin{multicols}{2}\\noindent', '\\begin{enumerate}']
990
991    tex_dec(exo, cor)
992
993    exo.append('\\end{enumerate}')
994    exo.append('\\end{multicols}')
995    cor.append('\\end{enumerate}')
996    cor.append('\\end{multicols}')
997    return (exo, cor)
998
999Decomposition.description = _(u'Décomposition de décimaux')
1000
1001
1002#===============================================================================
1003# Classer des nombres dans l'ordre
1004#===============================================================================
1005
1006
1007def choix_nombres():
1008    nb = []
1009    unite = random.randrange(10)
1010    for i in range(3):
1011        n = unite
1012        for j in range(i + 1):
1013            n = n + random.randrange(1, 10) * 10 ** (-(j + 1))
1014        nb.append(n)
1015    n = random.randrange(10) + random.randrange(10) / 10.0
1016    while n == nb[0]:
1017        n = random.randrange(10) + random.randrange(10) / 10.0
1018    nb.append(n)
1019    return nb
1020
1021
1022def classer(exo, cor):
1023    lnb = choix_nombres()
1024    random.shuffle(lnb)
1025    if random.randrange(2):
1026        ordre = "croissant"
1027    else:
1028        ordre = _(u"décroissant")
1029    exo.append(_(u"\\item Classer les nombres suivants dans l'ordre %s.\\par    " % 
1030             ordre))
1031    cor.append(_(u"\\item Classer les nombres suivants dans l'ordre %s.\\par    " % 
1032             ordre))
1033    phrase = ""
1034    for i in range(len(lnb)):
1035        if i:
1036            phrase += " \\kern1cm ; \\kern1cm "
1037        phrase += Affichage.decimaux(lnb[i], 0)
1038    exo.append(phrase)
1039    cor.append(phrase + "\\par")
1040    lnb.sort()
1041    if ordre == "croissant":
1042        ordre = "\\textless"
1043    else:
1044        ordre = "\\textgreater"
1045        lnb.reverse()
1046    phrase = ""
1047    for i in range(len(lnb)):
1048        if i:
1049            phrase += " \\kern1cm %s \\kern1cm " % ordre
1050        phrase += Affichage.decimaux(lnb[i], 0)
1051    cor.append(phrase)
1052
1053
1054
1055def ClasserNombres():
1056    exo = ["\\exercice", '\\begin{enumerate}']
1057    cor = ["\\exercice*", '\\begin{enumerate}']
1058    classer(exo, cor)
1059    classer(exo, cor)
1060    exo.append('\\end{enumerate}')
1061    cor.append('\\end{enumerate}')
1062    return (exo, cor)
1063
1064ClasserNombres.description = _(u'Classer des nombres décimaux')
Note: See TracBrowser for help on using the repository browser.