Bilan sequence caracteres

JFL -  
Phil_1857 Messages postés 1883 Date d'inscription   Statut Membre Dernière intervention   -
Bonjour,

J'ai du mal à faire le code pour avoir un bilan des séquences de caractères dans des listes du type l = ['a','a','a','b','b','b','a','c','c']. Ici par ex., je dois rendre comme résultat 3a, 3b, 1a, 2c.

En fait, une fois fait le bilan pour le premier caractère, comment puis- je passer au second puis au 3 eme etc. sachant qu'il faudrait créer d'autres listes. Je ne dois pas être sur la bonne piste pourriez -vous me conseiller? D'avance merci pour vos suggestions.


def bilan(l):
 n=[]
 i=0
 count=0
 n.append(l[i])
 while l[i+1]==l[i] :  
      n.append (l[i])
      i+=1
      count= count+i

 return  (count,n)
 

print(bilan(['a','a','a','b','b','b','a','c','c']))



Configuration: Windows / Firefox 101.0

15 réponses

  1. hibou_perfide
     
    Une autre façon de faire ; sans utiliser d'exception pour la gestion du dernier élément ; est de commencer par la fin de la séquence, de cette manière le fait d'en passer par des indices négatifs (parfaitement valide en python) ne jettera pas d'erreur, au contraire d'indice positif excédant la longueur de la séquence.

    sequence = 'aaabbbacc'
    groups = []
    count = 1
    current_element = sequence[-1]
    
    for i in range(len(sequence)-2, -2, -1):
        if sequence[i] == current_element:
            count += 1
        else:
            groups.append((current_element, count))
            current_element = sequence[i]
            count =1
    groups.reverse()
    print(groups)


    Et bien sûr, signalons que python fournit l'outil parfait pour aboutir à ce résultat,
    itertools.groupby
    .

    import itertools
    sequence = 'aaabbbacc'
    groups = []
    for element, group in itertools.groupby(sequence):
        groups.append((element, len(list(group))))
    print(groups)
    2
  2. Phil_1857 Messages postés 1883 Date d'inscription   Statut Membre Dernière intervention   169
     
    Bonjour,

    Très bien !
    Moi j'avais fait ça:

    L = ['a','a','b','a','a','c']
    L2 = []
    for k in range(len(L)):
        if(k == 0):
            previous = L[k]
            n=1
        else:
            if(L[k] == previous):
                n+=1
            else:
                L2.append(str(n)+previous)
                previous = L[k]
                n=1
    
        if(k == len(L)-1): L2.append(str(n)+previous)
    
    print(L2)
    
    2
    1. yg_be Messages postés 23437 Date d'inscription   Statut Contributeur Dernière intervention   1 588
       
      Pourquoi mettre dans la boucle un traitement spécifique à la première et à la dernière occurence?
      L = ['a','a','b','a','a','c']
      L2 = []
      previous = L[0]
      n=1
      for k in range(1,len(L)):
          if(L[k] == previous):
              n+=1
          else:
              L2.append(str(n)+previous)
              previous = L[k]
              n=1
      L2.append(str(n)+previous)
      
      print(L2)
      0
      1. Phil_1857 Messages postés 1883 Date d'inscription   Statut Membre Dernière intervention   169 > yg_be Messages postés 23437 Date d'inscription   Statut Contributeur Dernière intervention  
         
        Bon sang !

        Mais c'est bien sur !

        Encore plus court ! :-) :-)
        0
      2. jee pee Messages postés 31869 Date d'inscription   Statut Modérateur Dernière intervention   9 975 > Phil_1857 Messages postés 1883 Date d'inscription   Statut Membre Dernière intervention  
         
        Et on supprime previous
        L = ['a','a','b','a','a','c']
        L2 = []
        n=1
        for k in range(1,len(L)):
            if(L[k] == L[k-1]):
                n+=1
            else:
                L2.append(str(n)+L[k-1])
                n=1
        L2.append(str(n)+L[len(L)-1])
        
        print(L2)
        0
      3. Phil_1857 Messages postés 1883 Date d'inscription   Statut Membre Dernière intervention   169 > jee pee Messages postés 31869 Date d'inscription   Statut Modérateur Dernière intervention  
         
        Encore mieux !
        0
  3. mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   7 940
     
    Bonjour,

    Voici comment tu peux améliorer ton programme :

    #!/usr/bin/env python3
    
    def make_bilan(letters: str) -> list:
        letter = last_letter = None
        count = 0
        res = list()
        for letter in letters:
            if letter == last_letter:
                count += 1
            else:
                if last_letter is not None:
                    res.append((last_letter, count))
                last_letter = letter
                count = 1
        if count:
            res.append((letter, count))
        return res
    
    def format_bilan(b: list) -> str:
        return ", ".join(f"{count}{letter}" for (letter, count) in b)
    
    def bilan(letters: str) -> str:
        return format_bilan(make_bilan(letters))
                                      
    def test_bilan():                 
        for letters in "", "aaa", "aaabbbacc":
            print(f"{repr(letters)} --> {repr(bilan(letters))}")
                                                   
    test_bilan()


    Résultat :

    '' --> ''
    'aaa' --> '3a'
    'aaabbbacc' --> '3a, 3b, 1a, 2c'


    Bonne chance
    2
  4. JFL
     
    Phil_1857,
    Je te remercie vraiment pour tes suggestions et ta patience.

    Ci- dessous le code que j'ai pu écrire gràce à tes conseils. Je persiste à penser que ce n'était pas très facile à trouver ; je suis d'accord que plus on fait d'exercices mieux on integre les réflexes de base nécessaires pour progresser.

    Bonne continuation.

    def bilan(L):
    
     liste_finale=[]
    
     for k in (range(len(L))):
         if k==0:
          cpt=1
          lettre_precedente =(L[k])
         else:
             if L[k]==  lettre_precedente:
                     cpt+=1
             else :
                    liste_finale.append(lettre_precedente)
                    liste_finale.append(cpt)
                    cpt=1
                    lettre_precedente =(L[k])
         if k == len(L)-1:
                     liste_finale.append(lettre_precedente)
                     liste_finale.append( cpt)
                     return     liste_finale        
     
     
    print(bilan(['a','a','a','b','b','b','a','c','c']))
    1
    1. jee pee Messages postés 31869 Date d'inscription   Statut Modérateur Dernière intervention   9 975
       
      Bravo. Donc bien imaginer une solution avant d'écrire le code. J'ai l'habitude de dire que je fais tourner le programme dans ma tête avant de le saisir.

      Une remarque, si dans l'énoncé le format de sortie est impérativement
      3a, 3b, 1a, 2c
      tu pourrais faire :
                      liste_finale.append(lettre_precedente+str(cpt))
      1
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. yg_be Messages postés 23437 Date d'inscription   Statut Contributeur Dernière intervention   Ambassadeur 1 588
     
    bonjour,
    avant d'écrire du code, réfléchis à la séquence d'opérations à faire.
    écris et partage cette séquence.
    0
  7. Phil_1857 Messages postés 1883 Date d'inscription   Statut Membre Dernière intervention   169
     
    Bonjour,

    De plus, la liste Python possède une méthode count() qui permet de compter tel ou tel élément ...

    Et donc, ca peut se faire en 3 lignes de code
    0
    1. jee pee Messages postés 31869 Date d'inscription   Statut Modérateur Dernière intervention   9 975
       
      Bonjour,

      S'il fallait répondre a4 oui. Mais là on est sur le nombre de caractères qui se suivent, 3a, 3b, 1a, 2c.
      0
  8. JFL
     
    Merci pour tes suggestions.

    En fait j'ai utilisé la méthode count mais elle regroupe tout et j'avais comme réponse 4a, 3b, 1a, 2c au lieu de 3a, 3b, 1a, 2c ce qui ne convient pas.
    0
  9. Phil_1857 Messages postés 1883 Date d'inscription   Statut Membre Dernière intervention   169
     
    ah ok ...

    Bah, une boucle for sur la liste, en incrémentant un compteur tant que la lettre courante est la même que la précédente
    et c'est ok, et si ce n'est pas la même, on ajoute lettre et quantité dans une liste, on réinitialise le compteur et on recommence ... à la fin la nouvelle liste ressemble à ça:

    ['3a', '1b', '2a', '1c']
    0
  10. JFL
     
    merci pour ta réponse, je vais travailler ça.
    0
  11. Phil_1857 Messages postés 1883 Date d'inscription   Statut Membre Dernière intervention   169
     
    Si tu commence comme ça :

    for k in range(len(L)):


    2 cas particuliers

    k=0 : 1ere lettre de la liste (pas de lettre précédente)
    k = len(L)-1 : dernière lettre de la liste (pas de lettre suivante)
    0
  12. Phil_1857 Messages postés 1883 Date d'inscription   Statut Membre Dernière intervention   169
     
    Bonjour,

    Sinon, voici le pseudo-code qui détaille un peu plus ce que je te racontais plus haut:
    initialiser une liste_bilan vide
    for k in range(len(L)):
        si k=0 cas particulier 1ere lettre:
            initialiser le compteur
            lettre_precedente = L[k]
        sinon:
            si L[k] = lettre_precedente:
                on est sur la meme lettre: incrémenter le compteur
            sinon:
                on vient de changer de lettre, on peut mémoriser compteur et lettre_precedente:
                ajout à liste_bilan compteur+lettre_precedente
    
                et on part sur la nouvelle lettre:
                réinitialiser compteur
                lettre_precedente = L[k]
       
        si k = len(L)-1 cas particulier dernière lettre:
            ajout à liste_bilan compteur+lettre_precedente
    
    afficher liste_bilan
    0
  13. JFL
     
    Merci beaucoup car je n ai pas encore reussi a finaliser. Je trouve l'exercice difficile pour un debutant.
    0
    1. jee pee Messages postés 31869 Date d'inscription   Statut Modérateur Dernière intervention   9 975
       
      Comme l'a indiqué yg_be dès le départ, il te faut décrire la démarche à suivre, avant d'écrire le code lui-même. Là on va traiter les lettres une à une, en la comparant à la précédente, avec un compteur d’occurrences et 2 cas particuliers (première et dernière lettre). C'est ce que te donne Phil_1857 au dessus.

      Tu peux donner ton dernier code sur lequel tu buttes.
      0
    2. yg_be Messages postés 23437 Date d'inscription   Statut Contributeur Dernière intervention   1 588
       
      Il faut travailler sur beaucoup d'exercices pour ne pas rester débutant.
      0
  14. Phil_1857 Messages postés 1883 Date d'inscription   Statut Membre Dernière intervention   169
     
    Non, ce n'est pas difficile pour un débutant, ce n'est pas le problème de Python, ou C, ou C++ ..

    Le tout, c'est d'abord d'imaginer une méthode sur le papier, en dehors de tout problème de langage
    0
  15. mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   7 940
     
    Bonjour,

    Bonne idée le
    groupby
    , c'est plus élégant. Du coup, en combinant #19 et #20 :

    #!/usr/bin/env python3
    
    import itertools
    
    def make_bilan(letters):
        return [
            (letter, len(list(group)))
            for letter, group in itertools.groupby(letters)
        ]
    
    def format_bilan(b: list) -> str:
        return ", ".join(f"{count}{letter}" for (letter, count) in b)
    
    def bilan(letters: str) -> str:
        return format_bilan(make_bilan(letters))
    
    def test_bilan():
        for letters in "", "aaa", "aaabbbacc":
            print(f"{repr(letters)} --> {repr(bilan(letters))}")
    
    test_bilan()


    Résultat :

    '' --> ''
    'aaa' --> '3a'
    'aaabbbacc' --> '3a, 3b, 1a, 2c'
    0