#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # #from ..outils import ecrit_tex, valeur_alea, signe, pgcd, ppcm import random import string from ..outils.Affichage import TeX_quiz # # ------------------- ------------------- def valeurs(nb, entier=1): # renvoie les 2 listes contenant les opérateurs et les opérandes. listoperateurs = [ '+', '*', '-', '/', '(', '(', '(', '(', ')', ')', ')', ')', ] loperateurs = [] loperandes = [] i = 0 #nombre d'opérateurs créés p = 0 #nombre de parenthèses ouvertes cpt = 0 #compteur pour éviter que le programme ne boucle. while i < nb - 1: cpt = cpt + 1 if cpt > 10: #On recommence (cpt, i, p, loperateurs) = (0, 0, 0, []) if p: if loperateurs[-1] == '(': # On n'écrit pas 2 parenthèses à suivre operateur = listoperateurs[random.randrange(4)] else: operateur = listoperateurs[random.randrange(12)] elif loperateurs == []: # On ne commence pas par une parenthèse operateur = listoperateurs[random.randrange(4)] else: operateur = listoperateurs[random.randrange(8)] if nb > 3: test = ('-*/').find(operateur) >= 0 and \ loperateurs.count(operateur) < 1 or \ operateur == '+' and \ loperateurs.count(operateur) < 2 else: test = ('-*/+').find(operateur) >= 0 and \ loperateurs.count(operateur) < 1 if test: #On n'accepte pas plus de 1 produit, différence, quotient et de 2 #sommes ou parenthèses par calcul. if i == 0 or loperateurs[-1] != '(' or ('*/').find(operateur) < \ 0: #pas de * ou / dans une parenthèse. i = i + 1 loperateurs.append(operateur) elif operateur == '(' and (')+').find(loperateurs[-1]) < 0: #Il ne peut y avoir de ( après une ) ou après un + p = p + 1 loperateurs.append(operateur) elif operateur == ')': p = p - 1 loperateurs.append(operateur) while p > 0: loperateurs.append(')') p = p - 1 if entier: loperandes = [random.randrange(12) + 2 for i in range(nb)] else: loperandes = [((random.randrange(88) + 12) * 1.0) / 10 for i in range(nb)] return (loperateurs, loperandes) ####################### def affichage(loperateurs, loperandes): j = 0 #compteur des operateurs calcul = '%s' % nb_decimal((loperandes[0], )) for i in range(len(loperandes) - 1): if loperateurs[j] == ')': #Il reste une opération mais je ferme d'abord une ou plusieurs parenthèses cpt = 1 while loperateurs[j + cpt] == ')': cpt = cpt + 1 #j+cpt est la position de l'opération qui suit else: cpt = 0 if j + cpt < len(loperateurs) - 1: #Il reste au moins une opération, donc peut-etre une parenthèse ouvrante while loperateurs[j + cpt + 1] == '(': #j+cpt est la position de la dernière parenthèse ( cpt = cpt + 1 for k in range(cpt + 1): calcul = calcul + '%s' % loperateurs[j + k] calcul = calcul + '%s' % nb_decimal((loperandes[i + 1], )) j = j + cpt + 1 while j < len(loperateurs): calcul = calcul + '%s' % loperateurs[j] j = j + 1 calcul = (_('\\times ')).join(calcul.split('*', 2)) calcul = (_('\\div ')).join(calcul.split('/', 2)) return calcul def nb_decimal(a): # verifie si des nombres décimaux dans le tuple a sont en fait des nombres entiers et change leur type list = [] for i in range(len(a)): if str(a[i]).endswith('.0'): list.append(int(a[i] + .1)) else: list.append(('{,}').join(str(a[i]).split('.', 2))) return tuple(list) def verifie_calcul(listoperateurs, listoperandes, entier=1): #Vérifie que l'opération proposée est réalisable sans division # décimale ni nombre négatif p = 0 loperateurs = listoperateurs[-1] loperandes = listoperandes[-1] if len(loperandes) == 1: return (listoperateurs, listoperandes) else: nbpar = loperateurs.count('(') nbmul = loperateurs.count('*') nbdiv = loperateurs.count('/') if nbpar: index = -1 while p < nbpar: index = loperateurs[index + 1:].index('(') + index + 1 p = p + 1 if p < nbpar and loperateurs[index + 1:].index('(') > \ loperateurs[index + 1:].index(')'): nbpar = p if loperateurs[index + 2] == ')': a = calcul(loperandes[(index + 1) - nbpar], loperateurs[index + 1], loperandes[(index + 2) - nbpar], entier) if a != 'hp': al = loperateurs[:index] al.extend(loperateurs[index + 3:]) loperateurs = al al = loperandes[:(index + 1) - nbpar] al.append(a) al.extend(loperandes[index - nbpar + 3:]) loperandes = al listoperateurs.append(loperateurs) listoperandes.append(loperandes) return verifie_calcul(listoperateurs, listoperandes) elif nbmul or nbdiv: (indexm, indexd) = (100, 100) if nbmul: indexm = loperateurs.index('*') if nbdiv: indexd = loperateurs.index('/') index = min(indexm, indexd) a = calcul(loperandes[index], loperateurs[index], loperandes[index + 1], entier) if a != 'hp': al = loperateurs[:index] al.extend(loperateurs[index + 1:]) loperateurs = al al = loperandes[:index] al.append(a) al.extend(loperandes[index + 2:]) loperandes = al listoperateurs.append(loperateurs) listoperandes.append(loperandes) return verifie_calcul(listoperateurs, listoperandes) else: a = calcul(loperandes[0], loperateurs[0], loperandes[1], entier) if a != 'hp': loperateurs = loperateurs[1:] al = [a] al.extend(loperandes[2:]) loperandes = al listoperateurs.append(loperateurs) listoperandes.append(loperandes) return verifie_calcul(listoperateurs, listoperandes) def calcul(a, op, b, entier=1): #retourne 'hp' (hors programme) ou le résultat de l'opération if op == '+': return a + b elif op == '*': return a * b elif op == '-': if a > b: return a - b else: return 'hp' else: if (a * 100) % (b * 100) and entier: return 'hp' elif not entier and (a * 1000) % (b * 100): return 'hp' else: return a / b def main(): nb = 9 # nombre de calculs exo = ["\\exercice", _(u"Calculer les expressions suivantes en détaillant les calculs.\n"), "\\begin{multicols}{3}", "\\noindent"] cor = ["\\exercice*", _(u"Calculer les expressions suivantes en détaillant les calculs."), "\\begin{multicols}{3}", "\\noindent"] quiz = [u"cloze"] quiz_nom = _(u"Hiérarchie des opérations") quiz_exo_cor = _(u"Calcule les suivantes expressions utilisant la hiérarchie des opérations:
\n") quiz_exo_cor += u'\n' quiz_exo_cor += u'
\n' i = 0 while i < nb: if i < 3: #Les 3 premiers calculs ne comportent que 3 nombres (loperateurs, loperandes) = valeurs(3) elif i > 6: (loperateurs, loperandes) = valeurs(5, 0) #Les derniers calculs comportent des nombres décimaux else: (loperateurs, loperandes) = valeurs(6) if i > 6: list = verifie_calcul([loperateurs], [loperandes], entier=0) else: list = verifie_calcul([loperateurs], [loperandes], entier=1) if list != None: i = i + 1 for j in range(len(list[0])): if j == 0: exo.append("\\[ \\thenocalcul = %s \\]" % affichage(list[0][j], list[1][j])) exo.append('\\stepcounter{nocalcul}%') affichage_quiz = affichage(list[0][j], list[1][j]).replace("{,}", ",") quiz_exo_cor += (u"$$%s) \\; %s = $$" % (i, affichage_quiz)) if j == len(list[0]) - 1: cor.append("\\[ \\boxed{\\thenocalcul = %s} \\]" % affichage(list[0][j], list[1][j])) ## Cambia a NUMERICAL cuando el bug de quiz se solucione, también el ,0 a ,1 affichage_quiz = affichage(list[0][j], list[1][j]).replace("{,}", ",") quiz_exo_cor += (u"{1:SHORTANSWER:%s100%s%s}
\n" % ("%", "%", TeX_quiz(affichage_quiz,0))) if i == 5: quiz_exo_cor += u"
\n" cor.append('\\stepcounter{nocalcul}%') cor.append('\\stepcounter{nocalcul}%') else: cor.append("\\[ \\thenocalcul = %s \\]" % affichage(list[0][j], list[1][j])) exo.append("\\end{multicols}") cor.append("\\end{multicols}") quiz_exo_cor += u"
" quiz.append([quiz_nom, quiz_exo_cor, ""]) return (exo, cor, quiz)