Annonce

Réduire
Aucune annonce.

Besoin d'aide sur le loop d'une fonction Python

Réduire
X
 
  • Filtre
  • Heure
  • Afficher
Tout nettoyer
nouveaux messages

  • #46
    Rho là là… Ça bouge trop vite, on n’a plus le temps de répondre/coder ! :P

    Bon, d’abord, si tu es sûr que tu n’auras jamais A-B = 0, ça veut dire que la lettre Z est elle encodée par une différence de 26 (et 26%26 = 0), donc le -1, il faut le mettre dans le modulo, pas après (sinon, tu aura des @ à la place des Z): char((A-B-1)%26 + off).

    Ensuite, je me suis amusé à faire une petite app avec lecture de fichier en prime, ou directement en ligne de commande, et en utilisant argparse, bien plus sympa que sys.argv à utiliser. Attention, code py3 uniquement (on est moderne ou on ne l’est pas ).

    Code:
    #! /usr/bin/python3
    
    import sys
    
    def main():
        # The argparse is much nicer than directly using sys.argv...
        # Try 'modulo.py -h' to see! ;)
        import argparse
        parser = argparse.ArgumentParser(description="" \
                                     "Converts modulo 26 of the difference " \
                                     "between each successive numbers in a " \
                                     "letter.")
        parser.add_argument('-f', '--file',
                            help="A file containing all numbers.")
        parser.add_argument('-s', '--separator', default=" ",
                            help="A string to use to split the file elements.")
        parser.add_argument('numbers', nargs='*', type=int,
                            help="The numbers to process, ignored if a valid " \
                                 "file is given.")
        args = parser.parse_args()
    
        # Get all numbers directly given in the command line (they are already
        # converted in ints).
        numbers = args.numbers
        ret = []
        off = ord('A')
    
        # If a file path was given, try to open it, and use separator (which
        # defaults to simple space " ") to separate each number, then convert
        # it into an int, and make a list from all of them, replacing the
        # cl-given ones (if any).
        if args.file:
            with open(args.file, "r") as src:
                # Read everything, assuming we do not have millions of numbers.
                # This is a "list-comprehension", i.e. a shortcut for
                # txt = src.read() # Read the whole file.
                # txt_nbr = txt.split(args.separator) # Get each number (as text) into a list
                # numbers = [] # An empty list
                # for nbr in txt_nbr:
                #     numbers.append(int(nbr))
                numbers = [int(i) for i in src.read().split(args.separator)]
    
        if len(numbers) < 2:
            print("Not enough numbers given, aborting!")
            return -1
    
        B = numbers[0]
        for A in numbers[1:]:
            ret.append(chr(((A-B-1) % 26) + off))
            B = A
    
        # Convert the list f letters (ret) into a single string.
        print("".join(ret))
        return 0
    
    
    # These lines will only be executed if the script is the main one (i.e. the
    # one the interpreter was called with.)
    if __name__ == "__main__":
        # sys.exit will quit the program, returning the value returned by main
        # func.
        sys.exit(main())

    Commentaire


    • #47
      tu as testé le temps sur une boucle de 1000000 de fois pour voir, j'ai pas python 3 sur la main

      Commentaire


      • #48
        Envoyé par mont29 Voir le message
        Rho là là… Ça bouge trop vite, on n’a plus le temps de répondre/coder ! :P

        Bon, d’abord, si tu es sûr que tu n’auras jamais A-B = 0, ça veut dire que la lettre Z est elle encodée par une différence de 26 (et 26%26 = 0), donc le -1, il faut le mettre dans le modulo, pas après (sinon, tu aura des @ à la place des Z): char((A-B-1)%26 + off).
        Oh que c'est bien vu !

        Rien à redire sur le code, obviously

        Commentaire


        • #49
          Petite amélioration, avec une autre liste compréhension (yerkyerkyerk):

          Code:
          #! /usr/bin/python3
          
          import sys
          
          def main():
              # The argparse is much nicer than directly using sys.argv...
              # Try 'program.py -h' to see! ;)
              import argparse
              parser = argparse.ArgumentParser(description="" \
                                           "Converts modulo 26 of the difference " \
                                           "between each successive numbers in a " \
                                           "letter.")
              parser.add_argument('-f', '--file',
                                  help="A file containing all numbers.")
              parser.add_argument('-s', '--separator', default=" ",
                                  help="A string to use to split the file elements.")
              parser.add_argument('numbers', nargs='*', type=int,
                                  help="The numbers to process, ignored if a valid " \
                                       "file is given.")
              args = parser.parse_args()
          
              # Get all numbers directly given in the command line (they are already
              # converted in ints).
              numbers = args.numbers
              ret = []
              off = ord('A')
          
              # If a file path was given, try to open it, and use separator (which
              # defaults to simple space " ") to separate each number, then convert
              # it into an int, and make a list from all of them, replacing the
              # cl-given ones (if any).
              if args.file:
                  with open(args.file, "r") as src:
                      # Read everything, assuming we do not have millions of numbers.
                      # This is a "list-comprehension", i.e. a shortcut for
                      # txt = src.read() # Read the whole file.
                      # txt_nbr = txt.split(args.separator) # Get each number (as text) into a list
                      # numbers = [] # An empty list
                      # for nbr in txt_nbr:
                      #     numbers.append(int(nbr))
                      numbers = [int(i) for i in src.read().split(args.separator)]
          
              if len(numbers) < 2:
                  print("Not enough numbers given, aborting!")
                  return -1
          
              ret = [chr(((A-numbers[i]-1) % 26) + off) for i, A in enumerate(numbers[1:])]
          
              # Convert the list f letters (ret) into a single string.
              return "".join(ret)
          
          
          # These lines will only be executed if the script is the main one (i.e. the
          # one the interpreter was called with.)
          if __name__ == "__main__":
              # sys.exit will quit the program, returning the value returned by main
              # func.
              sys.exit(main())
          Et voici ce que ça me donne côté perfs (py3, quelques erreurs corrigées, et grand nombre de données plutôt que grand nombre de fois un faible nombre de données ) :

          Code:
          import sys
          from time import time
          from random import randint
          
          off = ord('A')
          
          def sol_1(val):
              chaine = ''
              for i in range(0, len(val)-1):
                  chaine += chr((val[i+1] - val[i]-1)%26 + off)
          
          
          def sol_2(val):
              chaine = []
              for i in range(0, len(val)-1):
                  chaine.append(chr((val[i+1] - val[i]-1)%26 + off))
              dummy = ''.join(chaine)
          
          
          def walkList(val):
              offset = 0
              ch = ''
              length = len(val)
              for i, elt in enumerate(val):
                  if (i<length-1 and i>=offset):
                      ch += chr(((val[i+1]-val[i]-1) % 26) + off)
          
          
          def oneliner(val):
              ret = [chr(((A-val[i]-1) % 26) + off) for i, A in enumerate(val[1:])]
              dummy = "".join(ret)
          
          
          def no_oneliner(val):
              chaine = ''
              for i, A in enumerate(val[1:]):
                  chaine += chr(((A-val[i]-1) % 26) + off)
          
          
          def test(fonction, val):
              start = time()
              for i in range(10):
                  fonction(val)
              print("Pour dix fois {} éléments, {} met : {} sec.".format(len(val), fonction.__name__, time() - start))
          
          
          val = [randint(-10000, 10000) for i in range(1000001)]
          for i in (sol_1, sol_2, walkList, oneliner, no_oneliner):
              test(i, val)
          résultats sans appel, quoi que serrés (trois appels, pour essayer de réduire l’incertitude) :

          Code:
          $ python3 ./Bureau/test2.py
          Pour dix fois 1000001 éléments, sol_1 met : 6.048012018203735 sec.
          Pour dix fois 1000001 éléments, sol_2 met : 6.014134883880615 sec.
          Pour dix fois 1000001 éléments, walkList met : 8.328366994857788 sec.
          Pour dix fois 1000001 éléments, oneliner met : 5.132487058639526 sec.
          Pour dix fois 1000001 éléments, no_oneliner met : 5.743177890777588 sec.
          
          $ python3 ./Bureau/test2.py
          Pour dix fois 1000001 éléments, sol_1 met : 6.587625026702881 sec.
          Pour dix fois 1000001 éléments, sol_2 met : 6.728790998458862 sec.
          Pour dix fois 1000001 éléments, walkList met : 8.511047840118408 sec.
          Pour dix fois 1000001 éléments, oneliner met : 5.27374792098999 sec.
          Pour dix fois 1000001 éléments, no_oneliner met : 5.842123985290527 sec.
          
          $ python3 ./Bureau/test2.py
          Pour dix fois 1000001 éléments, sol_1 met : 6.534747123718262 sec.
          Pour dix fois 1000001 éléments, sol_2 met : 6.4713051319122314 sec.
          Pour dix fois 1000001 éléments, walkList met : 7.82035493850708 sec.
          Pour dix fois 1000001 éléments, oneliner met : 5.796690225601196 sec.
          Pour dix fois 1000001 éléments, no_oneliner met : 6.138447046279907 sec.

          Commentaire


          • #50
            Wouah!, faut dire que mon code, il rame à fond!

            Commentaire

            Chargement...
            X