nouvel exo priorités opératoires

Les propositions de correctifs ou d'exercices pour Pyromaths.

Modérateur: Développeurs

nouvel exo priorités opératoires

Messagede fabienm » Dim 26 Mai 2013, 23:01

Bonsoir à tous,
Je bosse depuis quelques temps sur un nouvel exo de priorités opératoires, car je voulais plus de parenthèses ! J'ai essayé de reprendre l'ancien mais j'ai vite été découragé, c'est pas toujours simple de piger un code qu'on a pas écrit...
Bref, je suis arrivé à un stade où c'est utilisable.

Avantage :
- Mon code fonctionne sur des patterns, il y a 7 patterns de base, il est assez facile d'en créer d'autres sans rien toucher au reste du code.

Inconvénient :
- Je construis mes expressions en partant du résultat, à l'inverse du code de l'exo des priorités d'origines. Plus on complique l'expression, moins il est facile de contrôler les nombres obtenus... J'ai néanmoins beaucoup arrangé le hasard à ma sauce pour que les expressions soient le plus intéressantes possibles
- Les calculs nécessitent régulièrement quelques soustractions ou divisions à poser, perso je considère ça super important de savoir faire donc ça ne me gène pas, et les calculs à poser sont pas durs...

Voila un aperçu
Image

J'ai été courageux j'ai même codé la correction
Image

Je sais pas si je dois commit ça dans master... Je l'ai commit dans ma branche, environnement, mais elle diffère pas mal du pyromaths actuel... Je dépose le code ici

parentheses.py
Code: Tout sélectionner
#!/usr/bin/python
# -*- coding: utf-8 -*-

import random

def choix_nombre(debut=0,fin=100):
    """retourne un nombre x "aléatoire", mais suffisament intéressant
    à factoriser au cas où, entre 1 et < 300...
    on retourne x*y tel que debut <= x*y < fin"""
   
   
    if fin==1:
        # si on doit retourner zero, on le fait
        x = 0
        y = 0
    else:
        # sinon on retourne plus intéressant
        produits_cools = (36, 40, 42, 42, 45, 48, 48, 49, 49, 54, 54, 56, 56, 56, 63, 63, 63, 64, 64, 64, 64, 72, 72, 72, 72, 72, 81, 81, 81, 81, 81)
        while True:
            if random.randrange(110) < 75:
                # on met 110 pour être toujours capable de sortir du if
                # si jamais les bornes sont restrictives...
                x = produits_cools[random.randrange(len(produits_cools))]
                y=1
            else:
                # plus un facteur est intéressant, plus il est présent
                liste = (1, 2, 3, 4, 4, 4, 5, 6, 6, 6, 7, 8, 8, 8, 8, 9, 10, 10, 10, 11, 12, 12, 12, 12, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 16, 17, 18, 18, 18, 18, 19, 20, 20, 20, 20, 21, 21, 21, 22, 22, 22, 23, 24, 24, 24, 24, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 27, 28, 28, 28, 28, 29, 30, 30, 30, 30)
                x = liste[random.randrange(len(liste))]
                y = random.randrange(1, 10)
            if debut <= x*y and x*y < fin:
                break
    return x*y

def operation(resultat, prioritaire=0, interet=0):
    """Fabrique une operation avec un resultat donné
    A la fin, nb1 op nb2 = resultat
    prioritaire = 0 retourne n'importe quelle opé
    prioritaire = 1 retourne only + et - en opération
    prioritaire = 2 retourne only * et / en opération
    interet = 0 retourne l'opérande la plus intéressante
    des deux dans nb1
    interet = 1 retourne l'opérande la plus intéressante dans nb2
    interet fonctionne only si +- sont choisis
    """
    # je préfère voir apparaitre des produits que des quotients
    listoperateurs = [' \\times ', ' \\times ', ' \\times ', ' \\div ',' - ',' - ',' + ',' + ']
    if not prioritaire:
        # pas de préférence, on choisit au hasard
        prioritaire = random.randrange(1,3)

    # le code qui suit à plusieurs rôles :
    # - il permet de rendre les opérations retournées intéressantes
    #   suivant le résultat fourni
    # - il permet de maitriser la taille des opérandes, pour éviter
    #   qu'elle ne grossissent trop (choix_nombre nécessite < 300)
    if prioritaire == 2:
        if resultat < 6:
            # si le résultat est trop petit on force un quotient
            op = listoperateurs[3]
        elif resultat > 60:
            # si le résultat est trop grand on force un produit
            op = listoperateurs[0]
        else:
            op = listoperateurs[random.randrange(4)]
    elif prioritaire == 1:
        if resultat < 5:
            # si le résultat est trop petit on force une différence
            op = listoperateurs[4]
        elif resultat > 60:
            # si le résultat est trop grand on force une addition
            op = listoperateurs[6]
        else:
            op = listoperateurs[random.randrange(4,8)]

    if op == listoperateurs[6] or op == listoperateurs[7]:
        # +
        # on met resultat+1 pour que nb1 aie une valeur même si
        # resultat vaut 0
        if resultat == 0:
            (nb1,nb2)=(0,0)
        else:
            # le reste du temps, addition sans zéros
            if not interet:
                nb1 = choix_nombre(1,resultat+1)
                nb2 = resultat - nb1
            else:
                nb2 = choix_nombre(1,resultat+1)
                nb1 = resultat - nb2
    elif op == listoperateurs[4] or op == listoperateurs[5]:
        # -
        if not interet:
            nb1 = choix_nombre(resultat, 100 + resultat)
            nb2 = nb1 - resultat
        else:
            nb2 = choix_nombre(1,resultat+1)
            nb1 = resultat + nb2
               

    elif op in listoperateurs[:3]:
        # *
        ## on s'arrange pour que nb1 soit un diviseur de resultat
        if not resultat:
            # si resultat vaut 0 on ne peut pas prendre de diviseur
            # on construit alors un produit nul
            nb1 = 0
            nb2 = random.randrange(100)
        else:
            # on construit la liste des diviseurs, et on fabrique un produit
            liste_diviseurs = filter( lambda i:resultat%i==0, range(1, resultat+1))
            if len(liste_diviseurs) <= 2:
                nb1 = 1
            else:
                if random.randrange(2):
                    # 50% du temps, on retourne une multiplication
                    # avec deux "gros" facteurs pour apprendre les tables
                    # cela aura l'inconvénient de retourner souvent
                    # des soustractions sur une des opérandes
                    nb1 = liste_diviseurs[len(liste_diviseurs)/2]
                else:
                    # 50% du temps, on retourne une multiplicaiton
                    # avec possiblement un petit facteur, mais qui
                    # aura l'avantage pour le gros facteur de ne pas
                    # tout le temps retourner une soustraction
                    nb1 = liste_diviseurs[random.randrange(1,len(liste_diviseurs)-1)]
            nb2 = resultat / nb1
    elif op == listoperateurs[3]:
        # /
        nb2 = random.randrange(2,10) # pas 0 sinon on a une div par 0
        nb1 = nb2 * resultat
        # la division peut parfois mener à un nb1 trop gros
        while nb1 > 299:
            nb2 = random.randrange(2,10) # pas 0 sinon on a une div par 0
            nb1 = nb2 * resultat
    return (nb1, op, nb2)

def sommediff():
    resultat = random.randrange(100)
    choix = random.randrange(8)
    cor=[]
    if choix < 2:
        # a1 */ a2 +- b1 */ b2 = resultat
        # proba 1/4
        (a, op1, b)=operation(resultat, 1)
        (a1, op2, a2) = operation(a, 2)
        (b1, op3, b2) = operation(b, 2)
        calcul = str(a1) + op2 + str(a2) + op1 + str(b1) + op3 + str(b2)
        cor1 = str(a) + op1 + str(b)
        cor2 = resultat
        cor.append("\\[ \\thenocalcul = %s \\]" % calcul)
        cor.append("\\[ \\thenocalcul = %s \\]" % cor1)
        cor.append("\\[ \\thenocalcul = %s \\]" % cor2)
    elif choix == 2:
        # (a1 +- c1 */ c2) +- b = resultat
        # proba 1/8
        (a, op1, b)=operation(resultat, 1)
        #a2 a besoin d'être intéressant
        (a1, op2, a2) = operation(a, 1, 1)
        (c1, op3, c2) = operation(a2, 2)
        calcul = '(' + str(a1) + op2 + str(c1) + op3 + str(c2) + ')' + op1 + str(b)
        cor1 = '(' + str(a1) + op2 + str(a2) + ')' + op1 + str(b)
        cor2 = str(a) + op1 + str(b)
        cor3 = resultat
        cor.append("\\[ \\thenocalcul = %s \\]" % calcul)
        cor.append("\\[ \\thenocalcul = %s \\]" % cor1)
        cor.append("\\[ \\thenocalcul = %s \\]" % cor2)
        cor.append("\\[ \\thenocalcul = %s \\]" % cor3)
    elif choix == 3:
        # a +- (b1 +- c1 */ c2) = resultat
        # proba 1/8
        # b et b2 ont besoin d'etre intéressant
        (a, op1, b)=operation(resultat, 1, 1)
        (b1, op2, b2) = operation(b, 1, 1)
        (c1, op3, c2) = operation(b2, 2)
        calcul = str(a) + op1 + '(' + str(b1) + op2 + str(c1) + op3 + str(c2) + ')'
        cor1 = str(a) + op1 + '(' + str(b1) + op2 + str(b2) + ')'
        cor2 = str(a) + op1 + str(b)
        cor3 = resultat
        cor.append("\\[ \\thenocalcul = %s \\]" % calcul)
        cor.append("\\[ \\thenocalcul = %s \\]" % cor1)
        cor.append("\\[ \\thenocalcul = %s \\]" % cor2)
        cor.append("\\[ \\thenocalcul = %s \\]" % cor3)
    elif choix == 4:
        # ((c1 +- c2) */ a2) +- b = resultat
        # proba 1/8
        (a, op1, b)=operation(resultat, 1)
        (a1, op2, a2) = operation(a, 2)
        (c1, op3, c2) = operation(a1, 1)
        calcul = '(' + '(' + str(c1) + op3 + str(c2) + ')' + op2 + str(a2) + ')' + op1 + str(b)
        cor1 = '(' + str(a1) + op2 + str(a2) + ')' + op1 + str(b)
        cor2 = str(a) + op1 + str(b)
        cor3 = resultat
        cor.append("\\[ \\thenocalcul = %s \\]" % calcul)
        cor.append("\\[ \\thenocalcul = %s \\]" % cor1)
        cor.append("\\[ \\thenocalcul = %s \\]" % cor2)
        cor.append("\\[ \\thenocalcul = %s \\]" % cor3)
    elif choix == 5:
        # (a1 */ (c1 +- c2)) +- b = resultat
        # proba 1/8
        (a, op1, b)=operation(resultat, 1)
        #a2 a besoin d'être intéressant
        (a1, op2, a2) = operation(a, 2, 1)
        (c1, op3, c2) = operation(a2, 1)
        calcul = '(' + str(a1) + op2 + '(' + str(c1) + op3 + str(c2) + ')' + ')' + op1 + str(b)
        cor1 = '(' + str(a1) + op2 + str(a2) + ')' + op1 + str(b)
        cor2 = str(a) + op1 + str(b)
        cor3 = resultat
        cor.append("\\[ \\thenocalcul = %s \\]" % calcul)
        cor.append("\\[ \\thenocalcul = %s \\]" % cor1)
        cor.append("\\[ \\thenocalcul = %s \\]" % cor2)
        cor.append("\\[ \\thenocalcul = %s \\]" % cor3)
    elif choix == 6:
        # a +- ((c1 +- c2) */ b2) = resultat
        # proba 1/8
        # b a besoin d'être intéressant
        (a, op1, b)=operation(resultat, 1, 1)
        (b1, op2, b2) = operation(b, 2)
        (c1, op3, c2) = operation(b1, 1)
        calcul = str(a) + op1 + '(' + '(' + str(c1) + op3 + str(c2) + ')' + op2 + str(b2) + ')'
        cor1 = str(a) + op1 + '(' + str(b1) + op2 + str(b2) + ')'
        cor2 = str(a) + op1 + str(b)
        cor3 = resultat
        cor.append("\\[ \\thenocalcul = %s \\]" % calcul)
        cor.append("\\[ \\thenocalcul = %s \\]" % cor1)
        cor.append("\\[ \\thenocalcul = %s \\]" % cor2)
        cor.append("\\[ \\thenocalcul = %s \\]" % cor3)
    elif choix == 7:
        # a +- (b1 */ (c1 +- c2)) = resultat
        # proba 1/8
        # b a besoin d'être intéressant
        (a, op1, b)=operation(resultat, 1, 1)
        (b1, op2, b2) = operation(b, 2)
        (c1, op3, c2) = operation(b2, 1)
        calcul = str(a) + op1 + '(' + str(b1) + op2 + '(' + str(c1) + op3 + str(c2) + ')' + ')'
        cor1 = str(a) + op1 + '(' + str(b1) + op2 + str(b2) + ')'
        cor2 = str(a) + op1 + str(b)
        cor3 = resultat
        cor.append("\\[ \\thenocalcul = %s \\]" % calcul)
        cor.append("\\[ \\thenocalcul = %s \\]" % cor1)
        cor.append("\\[ \\thenocalcul = %s \\]" % cor2)
        cor.append("\\[ \\thenocalcul = %s \\]" % cor3)
    return (calcul, cor)

def exo_priorite(nb_exos, env):
    if env[1:]=='_colonnes':
        exo = ["\\exercice",
               u"Calculer les expressions suivantes en détaillant les calculs.\n"]
        cor = ["\\exercice*",
               u"Calculer les expressions suivantes en détaillant les calculs.",
               "\\begin{multicols}{3}", "\\noindent"]
    else:
        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"]

    for i in range(nb_exos):
        (l1, l2) = sommediff()
        exo.append("\\[ \\thenocalcul = %s \\]" % l1)
        cor.append(l2)
        exo.append("\\stepcounter{nocalcul}%")
        cor.append("\\stepcounter{nocalcul}%")
        cor.append("~\\")

    if env[1:]=='_colonnes':
        cor.append("\\end{multicols}")
    else:
        exo.append("\\end{multicols}")
        cor.append("\\end{multicols}")

    return (exo, cor)

#if __name__ == "__main__":
#    choix_nombre(1, 100)

fabienm
 
Messages: 28
Inscription: Mar 06 Nov 2012, 01:20

Re: nouvel exo priorités opératoires

Messagede Jérôme » Lun 27 Mai 2013, 19:59

Joli travail, mais j'ai l'impression que ça fait double emploi avec le précédent dans lequel il n'y a je pense pas grand chose à changer pour que ça te convienne.

L'ennui avec les exercices en doublon comme celui-ci, c'est qu'il faut en supprimer un. Il y a donc toujours un déçu de voir son travail rejeté. À l'avenir, je pense qu'il faudrait que les personnes qui retravaillent sur un sujet traité par un autre prévienne pour qu'on voit ensemble si ça se justifie et comment on gère les susceptibilités de chacun.

Qu'en pensez-vous ?
Pyromaths génère des fiches d'exercices et leur corrigé en toute simplicité.
Un programme multi-plateformes libre et gratuit sous licence GPL
Avatar de l’utilisateur
Jérôme
Administrateur - Site Admin
 
Messages: 1060
Inscription: Sam 26 Aoû 2006, 13:10
Localisation: Nantes

Re: nouvel exo priorités opératoires

Messagede fabienm » Lun 27 Mai 2013, 22:20

Haha, c'est à toi de décider, c'est toi le papa de pyromaths :)

Oui c'est vrai j'ai proposé de commit mais c'est pas une obligation... J'ai pondu ce code pour mes besoins personnels et après tout c'était le seul but. Je propose ici au cas ou ça intéresse quelqu'un d'autre :)

Je suis d'accord avec toi ça repose la question de la maintenance des exos
fabienm
 
Messages: 28
Inscription: Mar 06 Nov 2012, 01:20

Re: nouvel exo priorités opératoires

Messagede fabienm » Lun 27 Mai 2013, 23:16

Bon au passage j'avais pondu que des patterns de sommes ou différences, j'ai rajouté 6-7 patterns de produits/quotients, j'ai pas fait de screens mais ça donne bien en random.
fabienm
 
Messages: 28
Inscription: Mar 06 Nov 2012, 01:20


Retourner vers Propositions

Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 9 invités

cron