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

Last change on this file since 1666 was 1666, checked in by jrpelegrina, 3 years ago

Fix script to tooltip ex

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
26import locale
27from pyromaths.outils import Affichage, Arithmetique
28#===============================================================================
29# Écrire un nombre en lettres ou en chiffres
30#===============================================================================
31
32
33def NombreEnLettres(n, France=True):
34    unite = {
35        1: "un",
36        2: 'deux',
37        3: 'trois',
38        4: 'quatre',
39        5: 'cinq',
40        6: 'six',
41        7: 'sept',
42        8: 'huit',
43        9: 'neuf',
44        10: 'dix',
45        11: 'onze',
46        12: 'douze',
47        13: 'treize',
48        14: 'quatorze',
49        15: 'quinze',
50        16: 'seize',
51        17: 'dix-sept',
52        18: 'dix-huit',
53        19: 'dix-neuf',
54        }
55    dizaineF = {2: 'vingt', 3: 'trente', 4: 'quarante', 5: 'cinquante',
56                6: 'soixante', 7: "", 8: 'quatre-vingt', 9: ""}
57    dizaineB = {2: 'vingt', 3: 'trente', 4: 'quarante', 5: 'cinquante',
58                6: 'soixante', 7: 'septante', 8: 'octante', 9: 'nonante'}
59    coefs = {0: 'cent', 1: 'mille', 2: 'million', 3: 'milliard'}
60    result = ""
61
62    # Cas particulier de zéro
63    if n == 0:
64        result = u'zéro'
65    else:
66        coef = 0
67
68        while n > 0:
69
70        # Récupération de l'unité du bloc de trois chiffres en cours
71
72            u = n % 10
73            n = n // 10
74
75        # Récupération de la dizaine du bloc de trois chiffres en cours
76
77            d = n % 10
78            n = n // 10
79        # Traitement des dizaines
80
81            temp = ""
82
83        # Passage sur la dizaine inférieure pour 10 à 19
84        # et pour 70-79 90-99 dans le cas de la France
85
86            if d == 1 or (d == 7 or d == 9) and France:
87                d = d - 1
88                u = u + 10
89            if d > 1:
90                if France:
91                    if n:
92                        temp = '-' + dizaineF[d]
93                    else:
94                        temp = dizaineF[d]
95
96                    # Ajout du cas particulier de 'et' entre la dizaine et 1
97
98                    if d < 8 and (u == 1 or u == 11):
99                        temp = temp + '-et'
100                else:
101                    if n:
102                        temp = '-' + dizaineB[d]
103                    else:
104                        temp = dizaineB[d]
105
106                    # Ajout du cas particulier de 'et' entre la dizaine et 1
107
108                    if u == 1:
109                        temp = temp + '-et'
110
111        # ajout du texte de l'unité
112
113            if u > 0 and (d or n):
114                temp = temp + '-' + unite[u]
115            elif u > 0:
116                temp = unite[u]
117
118        # ajout du 's' à Quatre-vingt si rien ne suit
119        # if (result == '') and (d == 8) and (u == 0) and France : result = 's'
120
121            if d == 8 and u == 0 and France:
122                temp = temp + 's'
123            result = temp + result
124
125
126            # Récupération de la centaine du bloc de trois chiffres en cours
127
128            c = n % 10
129            n = n // 10
130            if c > 0:
131                temp = ""
132                if c > 1 and n:
133                    temp = '-' + unite[c]
134                elif c > 1:
135                    temp = unite[c]
136                if c == 1 and not n:
137                    temp = coefs[0]
138                else:
139                    temp = temp + '-' + coefs[0]
140
141                # Traitement du cas particulier du 's' à cent si rien ne suit
142
143                if result == "" and c > 1:
144                    result = 's'
145                result = temp + result
146
147            # Traitement du prochain groupe de 3 chiffres
148
149            if n > 0:
150                coef = coef + 1
151                i = n % 1000
152                if i > 1 and coef > 1:
153                    result = 's' + result
154
155                # Traitement du cas particulier 'mille' ( non pas 'un mille' )
156
157                if i == 1 and coef == 1:
158                    n = n - 1
159                    result = coefs[coef] + result
160                elif i > 0:
161
162                    result = '-' + coefs[coef] + result
163    return result
164
165def NombreEnLettres_es(n):
166    unite = {
167        1: 'uno',
168        2: 'dos',
169        3: 'tres',
170        4: 'cuatro',
171        5: 'cinco',
172        6: 'seis',
173        7: 'siete',
174        8: 'ocho',
175        9: 'nueve',
176        10: 'diez',
177        11: 'once',
178        12: 'doce',
179        13: 'trece',
180        14: 'catorce',
181        15: 'quince',
182        16: u'dieciséis',
183        17: 'diecisiete',
184        18: 'dieciocho',
185        19: 'diecinueve',
186        20: 'veinte',
187        21: 'veintiun',             #Está bien así, NO CORREGIR
188        22: u'veintidós',
189        23: u'veintitrés',
190        24: 'veinticuatro',
191        25: 'veinticinco',
192        26: u'veintiséis',
193        27: 'veintisiete',
194        28: 'veintiocho',
195        29: 'veintinueve',
196        }
197    dizaineE = {3: 'treinta', 4: 'cuarenta', 5: 'cincuenta',
198                6: 'sesenta', 7: 'setenta', 8: 'ochenta', 9: 'noventa'}
199    coefs = {0: 'cien', 1: 'mil', 2: 'mill', 3:'mil'}
200    coefc = {0: 'un', 1: 'ciento', 2: 'dosci', 3: 'tresci', 4:'cuatroci', 5:'quini',
201                6: 'seisci', 7: 'seteci', 8: 'ochoci', 9: 'noveci'}
202    result = ""
203   
204    #Cas particulier de zéro
205    if n == 0:
206        result = u'cero'
207    else:
208        coef = 0
209
210        while n > 0:
211
212        # Récupération de l'unité du bloc de trois chiffres en cours
213
214            u = n % 10
215            n = n // 10
216
217        # Récupération de la dizaine du bloc de trois chiffres en cours
218
219            d = n % 10
220            n = n // 10
221        # Traitement des dizaines
222
223            temp = ""
224
225        # Passage sur la dizaine inférieure pour 10 à 19
226        # et pour 70-79 90-99 dans le cas de la France
227
228            if d == 1:                  # Escribe los nº del 10 al 19 de la tabla
229                d = d - 1
230                u = u + 10
231            if d == 2:                  # Escribe los nº del 20 al 21 de la tabla
232                d = d - 1
233                u = u + 20
234            if d > 2:
235
236            # Ajout du cas particulier de 'et' entre la dizaine et 1
237
238                    if n:               # Escribe el resto del 30 al 99
239                        temp = ' ' + dizaineE[d]    # Añade espacio si es > 100
240                    else:
241                        temp = dizaineE[d]
242
243        # ajout du texte de l'unité
244
245            if u > 0 and d > 2:                         # Añade "y" de los nº entre 30 a 99
246                if u == 1 and coef > 0:                 # Usa "un" en lugar de "uno"
247                    temp = temp + ' y ' + coefc[0]
248                else:
249                    temp = temp + ' y ' + unite[u]
250            elif u > 0 and n:                           # Añade espacio si es > 100
251                if u == 21 and coef == 0: # Usa "veintiuno" en lugar de "veintiun" si <1000
252                    temp = temp + ' ' + unite[u] + 'o'
253                elif u == 1 and (coef > 0 and coef < 4):    # Usa "un" en lugar de "uno"
254                    if coef == 3:
255                        temp = temp                         # Usa "mil millones" en lugar de "un mil"
256                    else:
257                        temp = ' ' + coefc[0]
258                else:
259                    temp = temp + ' ' + unite[u]
260            elif u == 21 and d == 1 and coef == 0:  # Usa "veintiuno" cuando es 21
261                temp = unite[u] + 'o'
262            elif u == 1 and d == 0 and coef > 0:  # Usa "un" son numeros > 1000
263                temp = coefc[0]
264            elif u > 0:
265                temp = unite[u]
266
267            result = temp + result
268
269
270        # Récupération de la centaine du bloc de trois chiffres en cours
271
272            c = n % 10
273            n = n // 10
274            if c > 0:
275                temp = ""
276                if c == 1 and not d and not u:  # Usa "cien" en lugar de "un cien"
277                    temp = coefs[0]
278                elif c == 1:                      # Usa "ciento" para >100
279                    temp = coefc[1]
280                else:                           # Compone los nº > 200
281                    temp = coefc[c] + 'entos'
282
283        # Traitement du cas particulier du 's' à cent si rien ne suit
284
285                if n > 0 :                      # Añade espacio si es > 1000
286                    result = ' ' + temp + result
287                else:
288                    result = temp + result
289
290        # Traitement du prochain groupe de 3 chiffres
291
292            if n > 0:
293                coef = coef + 1
294                i = n % 1000
295
296          # Traitement du cas particulier 'mille' ( non pas 'un mille' )
297
298                if coef == 1 and i==1:        # No añade espacio en "mil"
299                    n = n - 1
300                    if n == 0:
301                        result = coefs[coef] + result
302                    else:
303                        result = ' ' + coefs[coef] + result
304                elif coef == 2:      # Usa "millones" en lugar de "millón"
305                    if i == 1 and n == 1:
306                        result = ' ' + coefs[coef] + u'ón' + result
307                    else:
308                        result = ' ' + coefs[coef] + 'ones' + result
309                elif i == 1 and coef == 3:      # No añade espacio en "mil millones"
310                    result = coefs[coef] + result
311                elif i > 0:
312                    result = ' ' + coefs[coef] + result
313
314    return result
315
316
317
318def nombreATrouver():
319    """a contient la liste des nombres à créer où il peut ne pas y avoir de
320    centaines, de centaines de milliers, d'unités ou de milliers"""
321
322    a = [random.randrange(100) + random.randrange(1000) * 10 ** 3,
323         random.randrange(1000) + random.randrange(100) * 10 ** 3,
324         random.randrange(1000) * 10 ** 3, random.randrange(1000)]
325    (lnb, liste) = ([], [])
326    for i in range(4):
327        lnb.append(random.randrange(1, 1000) * 10 ** 6 + a[i])
328    for i in range(4):
329        n = a[i]
330        if n % 1000:  # il y a des unités dans le nombre
331            e = random.randrange(1, 4)
332            lnb.append(n * 10 ** (-e))
333        else:
334            e = random.randrange(4, 7)
335            lnb.append(n * 10 ** (-e))
336    for i in range(8):
337        liste.append(lnb.pop(random.randrange(len(lnb))))
338    return liste
339
340def EcritNombreDecimal(n):
341    txt = ""
342    if n != int(n):
343        # n n'est pas un nombre entier
344        (e, d) = str(n).split('.')
345        (e, d) = (int(e), int(d))
346    else:
347        (e, d) = (int(n), 0)
348    if not d:
349        txt = NombreEnLettres(e)
350    elif e:
351        txt = NombreEnLettres(e)
352    if d:
353        partieDec = [u" dixième", u" centième", u" millième"]
354        if txt.rfind("un") == len(txt) - 2:
355
356        # le texte se finit par un. On l'accorde en genre avec unité
357
358            txt = txt + "e"
359        if e == 1:
360            txt = txt + u' unité et '
361        if e > 1:
362            txt = txt + u' unités et '
363        txt = txt + NombreEnLettres(d) + partieDec[len(str(n).split('.')[1]) - 
364                1]
365        if d > 1:
366            txt = txt + 's'
367    return txt
368
369def EcritNombreDecimal_es(n):
370    txt = ""
371    if n != int(n):
372        #n n'est pas un nombre entier
373        (e, d) = str(n).split('.')
374        (e, d) = (int(e), int(d))
375    else:
376        (e, d) = (int(n), 0)
377    if not d:
378        txt = NombreEnLettres_es(e)
379    elif e:
380        txt = NombreEnLettres_es(e)
381    if d:
382        partieDec = [u" décima", u" centésima", u" milésima"]
383        if e == 1:
384            txt = txt + u' unidad con '
385        if e > 1:
386            txt = txt + u' unidades con '
387        txt = txt + NombreEnLettres_es(d) + partieDec[len(str(n).split('.')[1]) -
388                1]
389        if d > 1:
390            txt = txt + 's'
391        txt = txt.replace("uno", "una")     # Cambio a femenino para decimales
392        txt = txt.replace("un ", "una ")    # Cambio a femenino para decimales
393        txt = txt.replace("tos", "tas")    # Cambio a femenino para decimales
394    return txt
395
396
397
398def EcritEnChiffre(exo, cor,lang=""):
399    lnb = nombreATrouver()
400    for i in range(len(lnb)):
401        exo.append("\\item " + eval('EcritNombreDecimal'+lang+'(lnb[i])') +
402                 " : \\dotfill")
403        cor.append("\\item " + eval('EcritNombreDecimal'+lang+'(lnb[i])') +
404                   " : ")
405        cor.append(Affichage.decimaux(lnb[i], 0) + '')
406
407
408def EcritEnLettre(exo, cor,lang=""):
409    lnb = nombreATrouver()
410    for i in range(8):
411        exo.append("\\item " + Affichage.decimaux(lnb[i], 0) + 
412                 " : \\dotfill")
413        cor.append("\\item " + Affichage.decimaux(lnb[i], 0) + 
414                " : ")
415        cor.append(eval('EcritNombreDecimal'+lang+'(lnb[i])') + '')
416
417
418def EcrireNombreLettre():
419
420    langue = locale.getdefaultlocale()[0][0:2]
421    if langue == "fr" or langue == "":
422        lang = ""
423    else:
424        lang = "_" + langue
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.