Partage
  • Partager sur Facebook
  • Partager sur Twitter

Boucle infinie......je ne trouve pas pourquoi

Sujet résolu
    15 août 2019 à 15:33:44

    Bonjour, 

    Je suis sur un problème de France IOI : http://www.france-ioi.org/algo/task.php?idChapter=656&idTask=2278

    (je ne sais pas si vous pouvez le voir si vous n'êtes pas inscrit ?)

    Bref le but est de lisser un signal. 

    On nous donne un nombre de mesures, une différence maximum entre les éléments à atteindre, et les mesures, et on doit ressortir un nombre de lissages nécessaires.

    Je vous donne maintenant mon code : 

    nbMesures = int(input())
    diffMax = float(input())
    listeMesures = []
    listeTempo = [0] * nbMesures
    lissage = 0
    ecartMax = 0
    encore = True
    
    for _ in range(nbMesures) :
       mesures = float(input())
       listeMesures.append(mesures)
    
    while encore : 
       for ind in range(nbMesures) :
          listeTempo[0] = listeMesures[0]
          listeTempo[nbMesures-1] = listeMesures[nbMesures-1]
          if 1 <= ind < nbMesures - 1 : 
             listeTempo[ind] = (listeMesures[ind-1]+listeMesures[ind+1])/2
             if abs(listeTempo[ind+1] - listeTempo[ind]) > ecartMax :
                ecartMax = abs(listeTempo[ind+1] - listeTempo[ind])
       lissage += 1
       
       listeMesures = listeTempo
       
       if ecartMax< diffMax :
          encore = False
      
    
    print(listeMesures)
    print(lissage)

    Problème : ma boucle est infinie....et je ne comprends pas pourquoi.

    Je calcule les moyennes et les mets dans une autre liste, ensuite je calcule l'écart maximum entre mes mesures (lissées), et si l'écart maximum est inférieur à celui demandé j'arrête avec 

    encore = False

    je ne vois pas ce qui cloche. 

    Merci pour vos précieuses lumières :)


    -
    Edité par Thia 15 août 2019 à 15:39:50

    • Partager sur Facebook
    • Partager sur Twitter
      15 août 2019 à 16:19:29

      Bonjour,

      Il y a pas mal de possibilités d’alléger le code. Ça aidera surement a trouver la raison :

      nbMesures = int(input())
      diffMax = float(input())
      listeMesures = []
      listeTempo = []  # pas besoin de le remplir de 0 .. et il faut se mefier du [qqch] * n
      lissage = 0
       
      listeMesures = [float(input()) for _ in range(nbMesures)]
       
      while True:
         ecartMax = 0  # il faut bien penser a reset l'ecart max à chaque itération ;).. sinon ca break pas
         listeTempo[0].append(listeMesures[0])                      # pas besoin de mettre ca dans le for loop
         for ind in range(1, nbMesures-1) :    # du coup tu peux changer le range et virer le if
             y = (listeMesures[ind-1]+listeMesures[ind+1])/2
             listeTempo.append(y)
             ecartMax = max(ecartMax , abs(listeTempo[ind-1] - listeTempo[ind]))  # le if peut etre remplacé par un simple max + changement d'index
         listeTempo[-1].append(listeMesures[-1])  # pas besoin de mettre ca dans le for loop et  -1 recup le dernier aussi
         ecartMax = max(ecartMax , abs(listeTempo[-2] - listeTempo[-1]))  # ecart avec le dernier index
      lissage += 1 listeMesures = listeTempo if ecartMax < diffMax : break # plus propre que changer le "encore" print(listeMesures) print(lissage)

      Tu perdra peut etre un tout petit peu de vitesse avec les append vs une liste de 0... A toi de voir ce que tu veux utiliser

      Et donc l'erreur vient de fait que tu ne reset pas ecartMax a chaque tour

      EDIT : Version avec declaration du tableau

      nbMesures = int(input())
      diffMax = float(input())
      listeMesures = []
      listeTempo = [0 for _ in range(nbMesures)]
      lissage = 0
       
      listeMesures = [float(input()) for _ in range(nbMesures)]
       
      while True:
         ecartMax = 0
         listeTempo[0] = listeMesures[0]
         for ind in range(1, nbMesures-1) :
             y = (listeMesures[ind-1]+listeMesures[ind+1])/2
             listeTempo[ind] = y
             ecartMax = max(ecartMax , abs(listeTempo[ind-1] - listeTempo[ind]))
         listeTempo[-1] = listeMesures[-1]
         ecartMax = max(ecartMax , abs(listeTempo[-2] - listeTempo[-1]))
         lissage += 1
          
         listeMesures = listeTempo
          
         if ecartMax < diffMax :
            break
         
      print(listeMesures)
      print(lissage)




      -
      Edité par coni63 15 août 2019 à 16:24:06

      • Partager sur Facebook
      • Partager sur Twitter
        15 août 2019 à 16:30:05

        coni63 a écrit:

        (...)

        Et donc l'erreur vient de fait que tu ne reset pas ecartMax a chaque tour

        (...)




        -
        Edité par coni63 il y a moins de 30s

        Oh mais oui c'est ça ! :p
        Bordel de *-/-* de */*-^*...1 heure que je m'use les yeux là-dessus, et j'ai même pas vu ça.....

        des fois.....on ne voit plus rien.

        coni63, je t'aime :lol: merci infiment

        Et merci pour les remarques sur le code.

        Je regarderai de + près demain (là j'ai plus le courage...)

        • Partager sur Facebook
        • Partager sur Twitter
          15 août 2019 à 20:19:46

          Attention, ton code même corrigé, contient encore plusieurs erreurs. La plus embêtante est l'écrasement d'un tableau par l'autre à ta ligne 23 (il faut plutôt les échanger, l'idée étant que tu disposes d'un tableau correct et d'un buffer). 

          On peut aussi ne pas utiliser de buffer (le tableau temporaire) mais le code est bien plus compliqué.

          • Partager sur Facebook
          • Partager sur Twitter
            15 août 2019 à 21:07:44

            Thia a écrit:

            des fois.....on ne voit plus rien.

            C'est pour ça qu'il faut faire des tests en remontant depuis les choses évidentes.

            Ici si ta boucle est infinie, c'est que ta condition de sortie (l'entrée dans le if ligne 25) ne s'exécute pas:

            • si elle s'exécute pas, c'est que ecartMax n'est jamais inférieur à diffMax
            • vu ton code, seule ecartMax varie, diffMax est constante, donc on colle un print(ecartMax) dans la boucle, et on regarde si c'est conforme à ce qu'on voulait.

            Et là normalement on trouve vite la solution.

            -
            Edité par LoupSolitaire 15 août 2019 à 21:08:38

            • Partager sur Facebook
            • Partager sur Twitter

            Blond, bouclé, toujours le sourire aux lèvres...

              15 août 2019 à 22:06:41

              LoupSolitaire a écrit:

              C'est pour ça qu'il faut faire des tests en remontant depuis les choses évidentes.

              Personnellement, quand j'ai une boucle vraiment infinie, je la casse sans trop tarder en une boucle for et j'analyse la condition. Dans le code posté plus haut ça donnerait :

              nbMesures = int(input())
              diffMax = float(input())
              listeMesures = []
              listeTempo = [0] * nbMesures
              lissage = 0
              ecartMax = 0
              encore = True
              
              for _ in range(nbMesures):
                  mesures = float(input())
                  listeMesures.append(mesures)
              
              #while encore :
              for nro in range(15):
                  print("n°:", nro)
                  print(listeMesures)
                  for ind in range(nbMesures):
                      listeTempo[0] = listeMesures[0]
                      listeTempo[nbMesures - 1] = listeMesures[nbMesures - 1]
                      if 1 <= ind < nbMesures - 1:
                          listeTempo[ind] = (
                              listeMesures[ind - 1] + listeMesures[ind + 1]) / 2
                          if abs(listeTempo[ind + 1] - listeTempo[ind]) > ecartMax:
                              ecartMax = abs(listeTempo[ind + 1] - listeTempo[ind])
                  lissage += 1
              
                  listeMesures = listeTempo
              
                  if ecartMax < diffMax:
                      encore = False
                  print(encore)
                  print("---------------------------------------")
                  
              
              print(listeMesures)
              print(lissage)
              

              et je regarde l'affichage :

              n°: 0
              [1.292, 1.343, 3.322, 4.789, -0.782, 7.313, 4.212]
              True
              ---------------------------------------
              n°: 1
              [1.292, 2.307, 3.066, 1.27, 6.051, 1.7149999999999999, 4.212]
              True
              ---------------------------------------
              n°: 2
              [1.292, 2.179, 1.7245, 3.88775, 2.801375, 3.5066875, 4.212]
              True
              ---------------------------------------
              n°: 3
              [1.292, 1.5082499999999999, 2.698, 2.7496875000000003, 3.1281875, 3.67009375, 4.212]
              True
              ---------------------------------------
              n°: 4
              [1.292, 1.995, 2.37234375, 2.750265625, 3.2101796875, 3.71108984375, 4.212]
              True
              ---------------------------------------
              n°: 5
              [1.292, 1.8321718750000002, 2.29121875, 2.7506992187500003, 3.23089453125, 3.7214472656249997, 4.212]
              True
              ---------------------------------------
              n°: 6
              [1.292, 1.7916093750000002, 2.2711542968750003, 2.7510244140625, 3.23623583984375, 3.724117919921875, 4.212]
              True
              ---------------------------------------
              n°: 7
              [1.292, 1.7815771484375, 2.26630078125, 2.751268310546875, 3.237693115234375, 3.7248465576171874, 4.212]
              True
              ---------------------------------------
              n°: 8
              [1.292, 1.779150390625, 2.2652093505859376, 2.7514512329101564, 3.238148895263672, 3.725074447631836, 4.212]
              True
              ---------------------------------------
              n°: 9
              [1.292, 1.7786046752929687, 2.2650279541015625, 2.751588424682617, 3.2383314361572264, 3.725165718078613, 4.212]
              True
              ---------------------------------------
              n°: 10
              [1.292, 1.7785139770507814, 2.265051200866699, 2.7516913185119627, 3.238428518295288, 3.725214259147644, 4.212]
              True
              ---------------------------------------
              n°: 11
              [1.292, 1.7785256004333494, 2.265108459472656, 2.7517684888839717, 3.238491374015808, 3.725245687007904, 4.212]
              True
              ---------------------------------------
              n°: 12
              [1.292, 1.778554229736328, 2.2651613593101496, 2.7518263666629785, 3.2385360268354413, 3.7252680134177205, 4.212]
              True
              ---------------------------------------
              n°: 13
              [1.292, 1.7785806796550747, 2.265203523159027, 2.751869774997234, 3.2385688942074773, 3.7252844471037383, 4.212]
              True
              ---------------------------------------
              n°: 14
              [1.292, 1.7786017615795133, 2.265235768288374, 2.7519023312479254, 3.238593389175832, 3.725296694587916, 4.212]
              True
              ---------------------------------------
              [1.292, 1.7786178841441869, 2.265260107696056, 2.751926748435944, 3.23861172151193, 3.725305860755965, 4.212]
              15

              Si ça résiste toujours, je passe au débogueur.

              • Partager sur Facebook
              • Partager sur Twitter
                16 août 2019 à 16:03:25

                Le problème c'est que.....c'était trop facile mon erreur.

                Donc j'ai lu et relu mon code dont j'étais pas très sure, sans penser que ça venait du calcul du maximum....Que normalement je fais les yeux fermés.

                Enfin, non, il faut pas, la preuve. Du coup je l'ai pas suffisamment analysé celui-là, j'ai pensé à un truc...mal fait ailleurs.

                Je débute, je n'ai pas encore assez d'expérience pour analyser et trouver mes erreurs malheureusement. MAis j'y travaille :p

                • Partager sur Facebook
                • Partager sur Twitter
                  16 août 2019 à 17:19:48

                  Thia a écrit:

                  Je débute, je n'ai pas encore assez d'expérience pour analyser et trouver mes erreurs malheureusement. MAis j'y travaille :p

                  Oui, ça viendra avec l'expérience :p

                  • Partager sur Facebook
                  • Partager sur Twitter

                  Blond, bouclé, toujours le sourire aux lèvres...

                    16 août 2019 à 17:30:01

                    Thia a écrit:

                    Le problème c'est que.....c'était trop facile mon erreur.

                    Donc j'ai lu et relu mon code dont j'étais pas très sure, sans penser que ça venait du calcul du maximum....Que normalement je fais les yeux fermés.

                    Enfin, non, il faut pas, la preuve. Du coup je l'ai pas suffisamment analysé celui-là, j'ai pensé à un truc...mal fait ailleurs.

                    Je débute, je n'ai pas encore assez d'expérience pour analyser et trouver mes erreurs malheureusement. MAis j'y travaille :p


                    Effectivement, il y a une erreur dans le calcul du maximum mais le plus gênant est en amont, c'est ton écrasement de liste. Au passage, il n'est pas nécessaire de calculer le maximum, il suffit juste de comparer les écarts à diffMax.
                    • Partager sur Facebook
                    • Partager sur Twitter
                      16 août 2019 à 17:53:29

                      PascalOrtiz a écrit:

                      Attention, ton code même corrigé, contient encore plusieurs erreurs. La plus embêtante est l'écrasement d'un tableau par l'autre à ta ligne 23 (il faut plutôt les échanger, l'idée étant que tu disposes d'un tableau correct et d'un buffer). 

                      On peut aussi ne pas utiliser de buffer (le tableau temporaire) mais le code est bien plus compliqué.

                      Je n'ai pas crée de compte sur France IOI pour tester le code mais en effet, il y a surement un soupcon à avoir sur cet assignement. Ajouter [:] pour avoir une copie leverait ce risque
                      • Partager sur Facebook
                      • Partager sur Twitter
                        16 août 2019 à 18:12:55

                        coni63 a écrit:

                        PascalOrtiz a écrit:

                        Attention, ton code même corrigé, contient encore plusieurs erreurs. La plus embêtante est l'écrasement d'un tableau par l'autre à ta ligne 23 (il faut plutôt les échanger, l'idée étant que tu disposes d'un tableau correct et d'un buffer). 

                        On peut aussi ne pas utiliser de buffer (le tableau temporaire) mais le code est bien plus compliqué.

                        Je n'ai pas crée de compte sur France IOI pour tester le code mais en effet, il y a surement un soupcon à avoir sur cet assignement. Ajouter [:] pour avoir une copie leverait ce risque

                        Oui mais ce serait faire une copie à chaque tour de boucle. Ici, il faut un tableau qui dispose de l'état du lissage à chaque étape et un buffer à extrémités fixes qui sert juste à se faciliter les calculs. On fait n-2 écritures par tour de boucle (l'autre tableau étant utilisé en lecture), à la fin de la boucle le buffer contient l'état courant du lissage et il faut donc échanger les deux tableaux comme on échangerait deux pointeurs en C.

                        • Partager sur Facebook
                        • Partager sur Twitter
                          19 août 2019 à 8:59:04

                          Je ne suis pas sûre d'avoir compris tout ce que vous avez dit :-°

                          Enfin je viens de tester mon programme.....il n'est pas bon, il réussit 13 tests/17. Donc y a un petit truc, quelque part, qui ne va pas.

                          Edit : en fait, quand il n'y a pas besoin de lissages, c'est à dire quand lissage =0, mon programme sort lissage =1

                          Faut que je trouve le moyen de comparer les mesures avant le premier lissage. Facile à faire, mais très lourd. Y a surement un moyen de faire ça sans que ce soit lourd. 

                          Bon, y encore un peu de boulot là-dessus :p

                          ---------------------------------------------------------------------------------------------------------------------------

                           Edit 2 : 

                          J'ai modifié mon code, pour rechercher d'abord ecartMax AVANT de lisser. Ce qui est en effet + logique.

                          Donc ça fonctionne... presque. Mon programme réussit 16 tests/17. Donc y a 1 cas que je n'ai pas géré, mais je ne sais pas lequel. On ne nous donne pas les données fournies pour les tests :(

                          Le code : 

                          nbMesures = int(input())
                          diffMax = float(input())
                          listeMesures = []
                          listeTempo = [0] * nbMesures
                          lissage = 0
                          ecartMax = 0
                          encore = True
                          
                          for _ in range(nbMesures) :
                             mesures = float(input())
                             listeMesures.append(mesures)
                          
                          while encore :
                          
                             for ind in range(nbMesures) :
                                if 1 <= ind < nbMesures - 1 : 
                                   if abs(listeMesures[ind] - listeMesures[ind-1]) > ecartMax :
                                      ecartMax = abs(listeMesures[ind] - listeMesures[ind-1])
                             
                             if ecartMax < diffMax :
                                encore = False
                                
                             else : 
                                listeTempo[0] = listeMesures[0]
                                listeTempo[nbMesures-1] = listeMesures[nbMesures-1]
                             
                                for ind in range(nbMesures) : 
                                   if 1 <= ind < nbMesures - 1 :
                                      listeTempo[ind] = (listeMesures[ind-1]+listeMesures[ind+1])/2
                             
                                lissage += 1
                             
                                listeMesures = listeTempo
                                listeTempo = [0] * nbMesures
                                ecartMax = 0
                          
                          print(lissage)

                          Si quelqu'un a une idée de ce qui n'est pas géré...je prends ^^

                          Edit 3 : c'est bon. C'était la ligne 16, il fallait mettre : if1<=ind <= nbMesures -1:

                          -
                          Edité par Thia 19 août 2019 à 10:04:06

                          • Partager sur Facebook
                          • Partager sur Twitter
                            19 août 2019 à 10:16:41

                            Ton erreur provient de la ligne 16 (je viens de tester ton code et après rectification, ça passe tous les tests). Au demeurant, cette ligne est assez maladroite vu la ligne 15.

                            EDIT

                            Je n'avais pas vu ton edit. Autant remplacer les lignes 15-16 :

                            for ind in range(nbMesures) :
                            if 1 <= ind < nbMesures - 1 :

                             par 

                            for ind in range(1, nbMesures) :

                            Comme te l'avais suggéré conio63. 

                            Sinon, c'est bien d'avoir persévéré même si ton code peut être amélioré et optimisé.

                            -
                            Edité par PascalOrtiz 19 août 2019 à 10:21:22

                            • Partager sur Facebook
                            • Partager sur Twitter

                            Boucle infinie......je ne trouve pas pourquoi

                            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                            • Editeur
                            • Markdown