source: pyromaths/trunk/fuentes/src/pyromaths/ex/cinquiemes/priorites.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: 9.7 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# from pyromaths.outils import ecrit_tex, valeur_alea, signe, pgcd, ppcm
24
25import random
26
27def valeurs(nb, entier=1):  # renvoie les 2 listes contenant les opérateurs et les opérandes.
28    listoperateurs = [
29        '+',
30        '*',
31        '-',
32        '/',
33        '(',
34        '(',
35        '(',
36        '(',
37        ')',
38        ')',
39        ')',
40        ')',
41        ]
42    loperateurs = []
43    loperandes = []
44    i = 0  # nombre d'opérateurs créés
45    p = 0  # nombre de parenthèses ouvertes
46    cpt = 0  # compteur pour éviter que le programme ne boucle.
47    while i < nb - 1:
48        cpt = cpt + 1
49        if cpt > 10:  # On recommence
50            (cpt, i, p, loperateurs) = (0, 0, 0, [])
51        if p:
52            if loperateurs[-1] == '(':  # On n'écrit pas 2 parenthèses à suivre
53                operateur = listoperateurs[random.randrange(4)]
54            else:
55                operateur = listoperateurs[random.randrange(12)]
56        elif loperateurs == []:
57
58            # On ne commence pas par une parenthèse
59
60            operateur = listoperateurs[random.randrange(4)]
61        else:
62            operateur = listoperateurs[random.randrange(8)]
63        if nb > 3:
64            test = ('-*/').find(operateur) >= 0 and \
65                   loperateurs.count(operateur) < 1 or \
66                   operateur == '+' and \
67                   loperateurs.count(operateur) < 2
68        else:
69            test = ('-*/+').find(operateur) >= 0 and \
70                   loperateurs.count(operateur) < 1
71        if test:
72
73            # On n'accepte pas plus de 1 produit, différence, quotient et de 2
74            # sommes ou parenthèses par calcul.
75
76            if i == 0 or loperateurs[-1] != '(' or ('*/').find(operateur) < \
77                0:  # pas de * ou / dans une parenthèse.
78                i = i + 1
79                loperateurs.append(operateur)
80        elif operateur == '(' and (')+').find(loperateurs[-1]) < 0:
81
82            # Il ne peut y avoir de ( après une ) ou après un +
83
84            p = p + 1
85            loperateurs.append(operateur)
86        elif operateur == ')':
87            p = p - 1
88            loperateurs.append(operateur)
89    while p > 0:
90        loperateurs.append(')')
91        p = p - 1
92    if entier:
93        loperandes = [random.randrange(12) + 2 for i in range(nb)]
94    else:
95        loperandes = [((random.randrange(88) + 12) * 1.0) / 10 for i in
96                      range(nb)]
97    return (loperateurs, loperandes)
98
99
100#######################
101
102
103def affichage(loperateurs, loperandes):
104    j = 0  # compteur des operateurs
105    calcul = '%s' % nb_decimal((loperandes[0],))
106    for i in range(len(loperandes) - 1):
107        if loperateurs[j] == ')':  # Il reste une opération mais je ferme d'abord une ou plusieurs parenthèses
108            cpt = 1
109            while loperateurs[j + cpt] == ')':
110                cpt = cpt + 1  # j+cpt est la position de l'opération qui suit
111        else:
112            cpt = 0
113        if j + cpt < len(loperateurs) - 1:  # Il reste au moins une opération, donc peut-etre une parenthèse ouvrante
114            while loperateurs[j + cpt + 1] == '(':  # j+cpt est la position de la dernière parenthèse (
115                cpt = cpt + 1
116        for k in range(cpt + 1):
117            calcul = calcul + '%s' % loperateurs[j + k]
118        calcul = calcul + '%s' % nb_decimal((loperandes[i + 1],))
119        j = j + cpt + 1
120    while j < len(loperateurs):
121        calcul = calcul + '%s' % loperateurs[j]
122        j = j + 1
123    calcul = ('\\times ').join(calcul.split('*', 2))
124    calcul = ('\\div ').join(calcul.split('/', 2))
125    return calcul
126
127
128def nb_decimal(a):  # verifie si des nombres décimaux dans le tuple a sont en fait des nombres entiers et change leur type
129    liste = []
130    for i in range(len(a)):
131        if str(a[i]).endswith('.0'):
132            liste.append(int(a[i] + .1))
133        else:
134            liste.append(('{,}').join(str(a[i]).split('.', 2)))
135    return tuple(liste)
136
137
138def verifie_calcul(listoperateurs, listoperandes, entier=1):
139
140    # Vérifie que l'opération proposée est réalisable sans division
141    # décimale ni nombre négatif
142
143    p = 0
144    loperateurs = listoperateurs[-1]
145    loperandes = listoperandes[-1]
146    if len(loperandes) == 1:
147        return (listoperateurs, listoperandes)
148    else:
149        nbpar = loperateurs.count('(')
150        nbmul = loperateurs.count('*')
151        nbdiv = loperateurs.count('/')
152        if nbpar:
153            index = -1
154            while p < nbpar:
155                index = loperateurs[index + 1:].index('(') + index + 1
156                p = p + 1
157                if p < nbpar and loperateurs[index + 1:].index('(') > \
158                    loperateurs[index + 1:].index(')'):
159                    nbpar = p
160            if loperateurs[index + 2] == ')':
161                a = calcul(loperandes[(index + 1) - nbpar], loperateurs[index +
162                           1], loperandes[(index + 2) - nbpar], entier)
163                if a != 'hp':
164                    al = loperateurs[:index]
165                    al.extend(loperateurs[index + 3:])
166                    loperateurs = al
167                    al = loperandes[:(index + 1) - nbpar]
168                    al.append(a)
169                    al.extend(loperandes[index - nbpar + 3:])
170                    loperandes = al
171                    listoperateurs.append(loperateurs)
172                    listoperandes.append(loperandes)
173                    return verifie_calcul(listoperateurs, listoperandes)
174        elif nbmul or nbdiv:
175            (indexm, indexd) = (100, 100)
176            if nbmul:
177                indexm = loperateurs.index('*')
178            if nbdiv:
179                indexd = loperateurs.index('/')
180            index = min(indexm, indexd)
181            a = calcul(loperandes[index], loperateurs[index], loperandes[index +
182                       1], entier)
183            if a != 'hp':
184                al = loperateurs[:index]
185                al.extend(loperateurs[index + 1:])
186                loperateurs = al
187                al = loperandes[:index]
188                al.append(a)
189                al.extend(loperandes[index + 2:])
190                loperandes = al
191                listoperateurs.append(loperateurs)
192                listoperandes.append(loperandes)
193                return verifie_calcul(listoperateurs, listoperandes)
194        else:
195            a = calcul(loperandes[0], loperateurs[0], loperandes[1],
196                       entier)
197            if a != 'hp':
198                loperateurs = loperateurs[1:]
199                al = [a]
200                al.extend(loperandes[2:])
201                loperandes = al
202                listoperateurs.append(loperateurs)
203                listoperandes.append(loperandes)
204                return verifie_calcul(listoperateurs, listoperandes)
205
206
207def calcul(a, op, b, entier=1):  # retourne 'hp' (hors programme) ou le résultat de l'opération
208    if op == '+':
209        return a + b
210    elif op == '*':
211        return a * b
212    elif op == '-':
213        if a > b:
214            return a - b
215        else:
216            return 'hp'
217    else:
218        if (a * 100) % (b * 100) and entier:
219            return 'hp'
220        elif not entier and (a * 1000) % (b * 100):
221            return 'hp'
222        else:
223            return a / b
224
225
226def priorites():
227    nb = 9  # nombre de calculs
228    exo = ["\\exercice",
229           u"Calculer les expressions suivantes en détaillant les calculs.\n",
230           "\\begin{multicols}{3}", "\\noindent"]
231    cor = ["\\exercice*",
232           u"Calculer les expressions suivantes en détaillant les calculs.",
233           "\\begin{multicols}{3}", "\\noindent"]
234    i = 0
235    while i < nb:
236        if i < 3:  # Les 3 premiers calculs ne comportent que 3 nombres
237            (loperateurs, loperandes) = valeurs(3)
238        elif i > 6:
239            (loperateurs, loperandes) = valeurs(5, 0)  # Les derniers calculs comportent des nombres décimaux
240        else:
241            (loperateurs, loperandes) = valeurs(6)
242
243        if i > 6:
244            liste = verifie_calcul([loperateurs], [loperandes], entier=0)
245        else:
246            liste = verifie_calcul([loperateurs], [loperandes], entier=1)
247        if liste != None:
248            i = i + 1
249            for j in range(len(liste[0])):
250                if j == 0:
251                    exo.append("\\[ \\thenocalcul = %s \\]" %
252                               affichage(liste[0][j], liste[1][j]))
253                    exo.append('\\stepcounter{nocalcul}%')
254                if j == len(liste[0]) - 1:
255                    cor.append("\\[ \\boxed{\\thenocalcul = %s} \\]" %
256                               affichage(liste[0][j], liste[1][j]))
257                    cor.append('\\stepcounter{nocalcul}%')
258                else:
259                    cor.append("\\[ \\thenocalcul = %s \\]" %
260                               affichage(liste[0][j], liste[1][j]))
261    exo.append("\\end{multicols}")
262    cor.append("\\end{multicols}")
263    return (exo, cor)
264
265priorites.description = _(u'Priorités opératoires')
Note: See TracBrowser for help on using the repository browser.