Partage
  • Partager sur Facebook
  • Partager sur Twitter

Algorithme calculatrice

avec python

    28 décembre 2021 à 10:41:06

    Bonjour alors je cherche a réaliser un programme qui demande a l'utilisateur un str du style '6*(1+3)' par exemple et retourne '18'

    Donc en gros comme ca:

    def calc(a):
        pass
    calc('6*(1+2)')
    #retourne 18

    Merci d'avance pour votre aide.

    • Partager sur Facebook
    • Partager sur Twitter
      28 décembre 2021 à 11:03:57

      Salut,

      Tu peux utiliser eval :

      def calc(a):
          return eval(a)
      
      print(calc('6*(1+2)'))



      • Partager sur Facebook
      • Partager sur Twitter
        28 décembre 2021 à 11:11:42

        Malheureusement je ne peut pas utiliser eval, le but de l'exercice est justement de coder eval.
        • Partager sur Facebook
        • Partager sur Twitter
          28 décembre 2021 à 11:18:20

          Ah ah, bah oui si tu nous le dis pas... :-°

          • Partager sur Facebook
          • Partager sur Twitter
            28 décembre 2021 à 11:22:52

            Désolé, du coup comment faire ?
            • Partager sur Facebook
            • Partager sur Twitter
              28 décembre 2021 à 11:55:37

              YesyesyesOkokok a écrit:

              Désolé, du coup comment faire ?

              Il faut analyser l'expression pour en faire une sorte d'arbre où les feuilles seront les entiers et les nœuds des opérations à réaliser... arrivé là on sait que l'expression est bien construite et on l'évalue en parcourant l'arbre.

              En cherchant sur Internet vous allez trouver aussi la même chose sous forme de recette de cuisine comme ici.

              Après tout dépend de votre approche du problème: ce n'est pas parce qu'il y a un consensus scientifique pour écrire une solution plutôt comme çà que d'autres n'existent pas... mais c'est à vous d'être inventif.

              • Partager sur Facebook
              • Partager sur Twitter
                28 décembre 2021 à 12:02:22

                Justement je travaille dans un abr et le but est de le calculer. Voici ce que j'ai fait :

                def exp(a,x='x',y='y'):
                    if not a.gauche().est_vide():
                        print("(", '',end='')
                        exp(a.gauche(),x,y)
                    if a.etiquette() == 'x':
                      print(x,'', end='')
                    elif a.etiquette() == 'y':
                      print(y,'', end='')
                    else:
                      print(a.etiquette(), '',end='')
                    if not a.droit().est_vide():
                        exp(a.droit(),x,y)
                        print(")", '',end='')



                • Partager sur Facebook
                • Partager sur Twitter
                  28 décembre 2021 à 13:59:33

                  YesyesyesOkokok a écrit:

                  Justement je travaille dans un abr et le but est de le calculer. Voici ce que j'ai fait :

                  Super... et alors, c'est quoi le soucis?

                  • Partager sur Facebook
                  • Partager sur Twitter
                    28 décembre 2021 à 15:29:31

                    Le soucis c'est que je n'ai pas su le faire.
                    • Partager sur Facebook
                    • Partager sur Twitter
                      28 décembre 2021 à 15:49:28

                      YesyesyesOkokok a écrit:

                      Le soucis c'est que je n'ai pas su le faire.


                      Ce ne sont pas les codes des plus faciles. Il faut maîtriser un peu la récursivité, les différents parcours d'arbres binaires ou pas,..

                      Si ce n'est pas le cas, commencer avec des articles ou des cours qu'on trouve sur Internet? Côté forum, on peut sans doute coder pour vous ou compléter un code pas trop mauvais mais il y a aussi des codes déjà tout faits (et eval... pour les autres)... Moi, je n'ai pas le temps de vous faire un cours particulier.

                      • Partager sur Facebook
                      • Partager sur Twitter
                        28 décembre 2021 à 16:00:36

                        j'ai commencé, mais cela n'abouti pas :

                        def calc(a):
                            if a.est_vide(): return 0
                            if a.etiquette()== '+': return int(calc(a.gauche()))+int(calc(a.droit()))
                            if a.etiquette()== '-': return int(calc(a.gauche()))-int(calc(a.droit()))
                            if a.etiquette()== '*': return int(calc(a.gauche()))*int(calc(a.droit()))
                            if a.etiquette()== '/': return int(calc(a.gauche()))/int(calc(a.droit()))



                        • Partager sur Facebook
                        • Partager sur Twitter
                          28 décembre 2021 à 16:31:05

                          C'est pas en tapant ce qu'il vous passe par la tête que vous allez y arriver: vous vous fatiguerez plus vite que la machine!

                          Trouvez un cours/tuto. comprenez comment se construit ce genre de code...

                          En tout cas, bon courage.

                          -
                          Edité par mps 28 décembre 2021 à 16:32:48

                          • Partager sur Facebook
                          • Partager sur Twitter
                            28 décembre 2021 à 17:06:45

                            Ce n'est pas ce qu'il me passe par la tête mon algo est réfléchi peut être maladroit mais réfléchit.

                            Voici mon résonnement: 

                            Fonction calc(arbre):

                            condition d'arrêt : l'arbre est vide dans ce cas retourne 0

                            ensuite selon le principe de récursivité on admet que le calcule du SAG et effectuer et que celui du SAD l'est aussi et donc selon l'étiquette on multiplie ou un additionne...

                            Excusez-moi et merci d'avance pour votre aide

                            • Partager sur Facebook
                            • Partager sur Twitter
                              28 décembre 2021 à 17:57:57

                              YesyesyesOkokok a écrit:

                              ensuite selon le principe de récursivité on admet que le calcule du SAG et effectuer et que celui du SAD l'est aussi et donc selon l'étiquette on multiplie ou un additionne...

                              Excusez-moi et merci d'avance pour votre aide


                              Rien qu'en lisant votre code vous devriez voir qu'il manque le traitement des feuilles (les nombres simples)... Puis vous avez peut être trop la tête dedans pour vous rendre compte que les constructions utilisés n'existent pas de base dans le langage. Techniquement on ne sait pas comment est construit l'arbre, ni s'il est valide...

                              Ce qui devrait vous conduire à poster beaucoup plus de code que pas grand monde lira.

                              C'est aussi ce qui rend l'exercice difficile: le manque de bras pour aider.... mais d'un autre côté, c'est un exercice qu'on vous a donné et vous aurez le corrigé un jour.

                              • Partager sur Facebook
                              • Partager sur Twitter
                                28 décembre 2021 à 18:11:07

                                Enfaite j'utilise un TAD ArbreBinaire avec pour fonction : etiquette ; gauche ; droit ; est_vide ; est_feuille
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  28 décembre 2021 à 18:22:44

                                  Ça se résout avec un arbre binaire, mais je ne crois pas qu'on appelle ça un ABR.
                                  Je l'ai déjà fait avec une classe Node contenant les éléments suivants:
                                  + identificateur (opérateur ou opérand)
                                  + valeur (nombre ou + - * /)
                                  + priorité
                                  + noeud père
                                  + noeud fils gauche
                                  + noeud fils droit
                                  Le tout est basé en grande partie sur les priorités.
                                  + la racine serait équivalente au '=' et sa priorité est 0
                                  (elle n'a pas de fils gauche)
                                  + tout autre noeud a une priorité supérieure.
                                  par exemple + et - valent 1, * et / valent 2, les opérand valent plus (par ex. 10)
                                  on a une priorité de base qu'on ajoute aux autres priorités (0 au départ)
                                  + quand on rencontre une '(' on augmente la priorité de base (par ex. 100)
                                  + quand on rencontre une ')' on diminue la priorité de base d'autant.
                                  L'idée est d'essayer d'ajouter le noeud courant au fils droit du dernier inséré.
                                  On remonte de père en père jusqu'à ce que la priiorité soit <= au nouveau
                                  On place la séquence suivante du dernier remontté de priorité supérieure comme fils gauche du précédent
                                  et on place le nouveau noeud comme fils droit.
                                  Je ne sais pas si j'ai été assez clair ...
                                  Pour l'évaluation, ça se fait récursivement assez facilement.

                                  edit:

                                  On peut valider l'arbre

                                  + tout opérand doit avoir 0 fils

                                  + tout opérateur doit avoir 2 fils

                                  + etc.

                                  -
                                  Edité par PierrotLeFou 28 décembre 2021 à 18:33:04

                                  • Partager sur Facebook
                                  • Partager sur Twitter

                                  Le Tout est souvent plus grand que la somme de ses parties.

                                    28 décembre 2021 à 18:42:42

                                    Je n'ai pas très bien compris votre méthode récursive

                                    -
                                    Edité par YesyesyesOkokok 28 décembre 2021 à 18:42:57

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      28 décembre 2021 à 19:03:34

                                      La construction de l'arbre ne se fait pas de façon récursive (en tout cas, pas tout-à-fait)
                                      Par exemple, si j'ai a+b*c
                                      je place a en premier à la droite de la racine
                                      j'ai le + ensuite. Le + a une priorité inférieure à a
                                      le + doit être placé à la droite de la racine et le a placé à la gauche du +
                                      je rencontre b que je place à la droite de +
                                      je rencontre *. Il a une priorité inférieure au b
                                      je le fais remonter au dessous du + et le b se retrouvera à la gauche du *
                                      je rencontre c que je place à la droitte de *
                                      etc.

                                      edit:
                                      Pour l'évaluation, on aurait:
                                      def evaluation(node):
                                          if node.id == operand: return valeur
                                          elif node.id == +: return evaluation(node.gauche) + evaluation(node.droite)
                                          elif:
                                              ...

                                      -
                                      Edité par PierrotLeFou 28 décembre 2021 à 19:24:37

                                      • Partager sur Facebook
                                      • Partager sur Twitter

                                      Le Tout est souvent plus grand que la somme de ses parties.

                                        28 décembre 2021 à 19:20:10

                                        oui par raport la construction de l'arbre je sais voici un exemple:

                                        expression = AB('*', feuille(4), AB('-', feuille(3), feuille(1)))
                                        #Ce qui vaut : 4 * ( 3 - 1 )


                                        Moi mon problème c'est l'algorithme de calcul qui lui est récursif

                                        -
                                        Edité par YesyesyesOkokok 28 décembre 2021 à 19:21:10

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          28 décembre 2021 à 19:37:54

                                          Pas évident de représenter un arbre ici ...
                                          Dans mon cas la racine n'a qu'un fils droit soit le +
                                          le + a les fils [a, *]
                                          le * a les fils [b, c]
                                          As-tu compris ma fonction récursive?
                                          • Partager sur Facebook
                                          • Partager sur Twitter

                                          Le Tout est souvent plus grand que la somme de ses parties.

                                            28 décembre 2021 à 21:19:15

                                            Y'a-t-il pas un moyen de faire plus simple un truc dans ce style la:

                                            def calc(a):
                                                if a.est_vide(): return 0
                                                if a.etiquette()== '+': return int(calc(a.gauche()))+int(calc(a.droit()))
                                                if a.etiquette()== '-': return int(calc(a.gauche()))-int(calc(a.droit()))
                                                if a.etiquette()== '*': return int(calc(a.gauche()))*int(calc(a.droit()))
                                                if a.etiquette()== '/': return int(calc(a.gauche()))/int(calc(a.droit()))

                                            ???

                                            -
                                            Edité par YesyesyesOkokok 28 décembre 2021 à 21:45:48

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              28 décembre 2021 à 22:19:21

                                              Avec Python, on pourrait écrire quelque chose comme:

                                              >>> from operator import mul,truediv,add,sub
                                              >>> a = (mul, 4, (sub, 3, 1))
                                              >>> def calc(a):
                                              ...     if isinstance(a, int):
                                              ...        return a
                                              ...     o, l, r = a
                                              ...     return o(calc(l), calc(r))
                                              ...
                                              >>> calc(a)
                                              8
                                              >>>
                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                28 décembre 2021 à 22:46:35

                                                Aaaaa d'accord je comprend. Mais n'y aurait-il pas un moyen de le faire sans importer operator ???
                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  29 décembre 2021 à 2:51:23

                                                  Je ne sais pas comment tu fais pour construire ton arbre.
                                                  Je définissais une classe Node comme suit:
                                                  class Node:
                                                      def __init__(self, id='', valeur='', priorite=0, pere=None, gauche=None, droit=None):
                                                          self.id = id
                                                          self.valeur = valeur
                                                          self.priorite = priorite
                                                          self.pere = pere
                                                          self.gauche = gauche
                                                          self.droit = droit
                                                  -
                                                  On commence par définir la racine:
                                                  racine = Node()   # Les valeurs par défaut sont correctes
                                                  courant = racine   # On va ajouter au fils droit de la racine
                                                  au départ base = 0   # priorité de base
                                                  J'ai un dictionnaire des priorités:
                                                  dicPriorite = {'+': 1, '-': 1, '*': 2, '/': 2}
                                                  Je puise les éléments dans une liste (el)
                                                  (je suppose que le parsing a éliminé les éléments indésirables)
                                                  if el == '(':
                                                      base += 100
                                                  elif el == ')':
                                                      base -= 100   # à la fin, base devrait être 0
                                                  # Ce qui suit pourrait être: if el in dicPriorit.keys():
                                                  elif el in "+-*/":   # si opérateur
                                                      nouveau = Node(id='operateur', valeur=el, priorit=base+dicPriorite[el])
                                                  else:   # si opérand
                                                      nouveau = Node(id='operand', valeur=int(el), priorit=base+10)   # Je décide que la priorité est 10 (> aux opérateurs)
                                                  Pour placer le noeud dans l'arbre
                                                  while nouveau.priorite < courant.priorit:   # On remonte dans l'arbre
                                                      courant = courant.pere   # On ne peut pas aller plus loin que la racine
                                                  nouveau.gauche = courant.droit
                                                  if courant.droit is not None:
                                                      nouveau.gauche.pere = courant
                                                  courant.droit =nouveau
                                                  nouveau.pere = courant
                                                  courant = nouveau
                                                  Et on va chercher le suivant dans la liste ...
                                                  Si tu ne veux pas utiliser le module operator, regardes mon ébauche de solution

                                                  edit:

                                                  J'ai écrit la fonction d'évaluation en fonction de mon arbre et ma définition des noeuds.
                                                  Si je place bien un int dans la valeur, je pourrais utiliser isinstance pour savoir si c'est un opérand.
                                                  (je n'aurais plus besoin de node.id)
                                                  -
                                                  def my_eval(node):
                                                          # Dictionnaire associant un symbole avec la fonction (ou opérateur)
                                                      dicOpe = {'+': add, '-': sub, '*': mul, '/': truediv}
                                                      if node.id == 'operand':
                                                          return node.valeur
                                                      else:
                                                          return dicOpe[node.valeur](my_eval(node.gauche), my_eval(node.droit))

                                                  Et on commence avec:

                                                  resultat = my_eval(racine.droit)

                                                  -
                                                  Edité par PierrotLeFou 29 décembre 2021 à 4:20:34

                                                  • Partager sur Facebook
                                                  • Partager sur Twitter

                                                  Le Tout est souvent plus grand que la somme de ses parties.

                                                    29 décembre 2021 à 7:33:37

                                                    YesyesyesOkokok a écrit:

                                                    Aaaaa d'accord je comprend. Mais n'y aurait-il pas un moyen de le faire sans importer operator ???

                                                    Associer l'opération '+-*/' a une fonction => dictionnaire. puis si vous avez envie de réécrire vos fonctions plutôt qu'utiliser les existantes... çà fera juste plus de lignes de code à écrire.

                                                    -
                                                    Edité par mps 29 décembre 2021 à 8:29:09

                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      29 décembre 2021 à 7:53:45

                                                      Pas bête l'idée de réécrire les fonctions ...
                                                      Elles feront probablement la même chose de toute façon ...
                                                      Si on ne veut pas de truediv mais une division entière, on pourra le faire.
                                                      La fonction  div  n'est pas reconnue chez moi, c'est normal?
                                                      • Partager sur Facebook
                                                      • Partager sur Twitter

                                                      Le Tout est souvent plus grand que la somme de ses parties.

                                                        29 décembre 2021 à 10:42:01

                                                        Voici comment mon arbre est coder:

                                                        class AB:
                                                            def __init__(self, *args):
                                                                if len(args) == 0:
                                                                    self.__contenu = None
                                                                else:
                                                                    ''' etiquette en 0, puis sous arbre gauche et sous arbre droit.'''
                                                                    self.__contenu = (args[0], args[1], args[2])
                                                        
                                                            def etiquette (self):
                                                                ''' renvoie l étiquette du noeud.'''
                                                                return(self.__contenu[0])
                                                        
                                                            def gauche(self):
                                                                ''' renvoie le sous arbre gauche du noeud.'''
                                                                return(self.__contenu[1])
                                                        
                                                            def droit(self):
                                                                ''' renvoie le sous arbre droit du noeud.'''
                                                                return(self.__contenu[2])
                                                        
                                                            def est_vide(self):
                                                                ''' prédicat pour tester si un arbre est vide.'''
                                                                return self.__contenu == None
                                                        
                                                            def est_feuille(self):
                                                                ''' prédicat pour tester si un arbre est une feuille ou non ( = un arbre de taille 1).'''
                                                                return (not self.est_vide()
                                                                and self.gauche().est_vide()
                                                                and self.droit().est_vide())



                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          29 décembre 2021 à 12:29:55

                                                          PierrotLeFou a écrit:

                                                          La fonction  div  n'est pas reconnue chez moi, c'est normal?


                                                          a // b est operator.floordiv

                                                          YesyesyesOkokok a écrit:

                                                          Voici comment mon arbre est coder:

                                                          Regardez comment le mien est codé: des triplets ou le premier item est une opération et les suivants un triplet (sous arbre) ou une feuille (un nombre). C'est ce que vous devez revoir et dans l'arbre et dans calc.

                                                          -
                                                          Edité par mps 29 décembre 2021 à 13:34:56

                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                            29 décembre 2021 à 17:53:00

                                                            Merci mps pour l'info, je pensais que c'était pour des float.
                                                            Ce que YesyesyesOkokok veut faire est évaluer l'expression avec un arbre.
                                                            Ce que tu suggères oblige à construire l'expression sous forme de chaîne et utiliser eval() pour l'évaluer.
                                                            Ce que j'ai fait ne respecte pas tout à fait la philosophie de la POO, mais c'est nettement plus simple.
                                                            Je réussis à tout coder en incluant la validation en environ 75 lignes.

                                                            • Partager sur Facebook
                                                            • Partager sur Twitter

                                                            Le Tout est souvent plus grand que la somme de ses parties.

                                                              29 décembre 2021 à 19:08:16

                                                              PierrotLeFou a écrit:

                                                              Ce que tu suggères oblige à construire l'expression sous forme de chaîne et utiliser eval() pour l'évaluer.


                                                              Relis mon code: ça ne fait pas du tout ça... Juste que je ne m'embête pas à définir une classe pour fabriquer l'arbre: des triplets représentés par des tuples définissent un noeud et si les suivants sont des nombres, on est sur une feuille.
                                                              • Partager sur Facebook
                                                              • Partager sur Twitter

                                                              Algorithme calculatrice

                                                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                              • Editeur
                                                              • Markdown