Afficher sur une ligne la longueur et le nombre de mots de cette longueur

Le problème exposé dans ce sujet a été résolu.

Bonjour à tous et merci d’avance de votre aide. Mon problème c’est que je suis bloquée sur un exercice. Voilà le sujet :

En étudiant différents types de textes (romans, lois, article de journaux…), on se rend compte que non seulement les mots utilisés ne sont pas les mêmes mais aussi que leurs longueurs sont statistiquement différentes : par exemple, il est beaucoup plus fréquent de trouver de longs mots complexes dans un article de loi que dans un livre pour enfants. Afin d’essayer de déterminer automatiquement à quelle catégorie appartient un livre, on souhaite déterminer le nombre de mots de 1 lettre, 2 lettres, 3 lettres… qu’il contient.

  • Contraintes : Le texte contient un ensemble de mots, séparés par des espaces, sans aucun signe de ponctuation. Chaque mot contient au plus 100 caractères.

  • Entrée : La première ligne contient deux entiers : nbLignes et nbMots. Chacune des nbLignes lignes suivantes contient nbMots mots.

  • Sortie : Pour chaque longueur de mot possible, et uniquement s’il y avait des mots de cette longueur dans le texte, vous devez afficher sur une ligne la longueur et le nombre de mots de cette longueur, séparés par un deux-points (il faut mettre un espace de chaque côté du deux-points).

Exemple :
entrée :
2 7
Qui vole un oeuf vole un boeuf
Une abeille vaut mieux que mille mouches

sortie :
2 : 2
3 : 3
4 : 4
5 : 3
7 : 2

Voilà le sujet. Alors mon problème c’est que mon programme marche seulement si :
- l’utilisateur ne rentre qu’une seule ligne
- et tous les mots sont différents. (si il y a deux fois "et" par exemple, ça ne marche pas bien.)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
nbLignes, nbMots = map(int, input().split(" "))
texte = input()
liste = []
motLong = ""
premierMot = ""
a = 1
b = 1
R1 = []
R2 = []
S = []
R3 = []

for mot in texte.split(" ") :
    liste.append(mot)
    liste.sort(key=len)
    if len(mot) > len(motLong) :
        motLong = mot
        longueurMax = len(motLong)+1

for mot in liste :
    if len(premierMot) != len(mot) :
        premierMot = mot

    for a in range(longueurMax) :
        if premierMot == mot and len(mot) == a :
            R1.append(a)
            S.append(b)
        elif premierMot != mot and len(mot) == a :
            R2.append(a)
            S.append(b)
R3 = R1 + R2

for z in range(longueurMax) :
    for y in R1 :
        x = R3.count(z)
        if x != 0 and z == y :
            print(y, " : ", x)

Voilà ! Je débute donc je me suis certainement compliqué la vie.

Pour quand il y a deux mêmes mots j’avais pensé utiliser un compteur mais je ne sais pas trop comment m’y prendre. Et pour plus d’une ligne, j’ai voulu utiliser for i in range(nbLignes) : mais je n’arrive pas à afficher ce que je veux. Je pense que c’est parce que j’utilise les mêmes variables donc ça coince au niveau de mes listes.

Voilà, merci d’avance

Salut !

si l’utilisateur ne rentre qu’une seule ligne

Je pense que c’est dû au texte = input() ligne 2. En Python, input() n’accepte qu’une seule ligne, il considère la touche Entrée comme une validation. Pour avoir deux lignes, tu as deux solutions simples :

  • échapper le saut de ligne en écrivant \n au lieu d’appuyer sur Entrée ;
  • mettre plusieurs input() (un par ligne désirée) et les mettre à la chaine.

Si tu veux utiliser un module de compteur, tu peut regarder du côté de Counter, il accepte n’importe quel itérable (dans ton cas, une liste de mots) et sort un dictionnaire avec le compte de chaque mot. ;)

+0 -0

Bonsoir !

Je pense que c’est dû au texte = input() ligne 2. En Python, input() n’accepte qu’une seule ligne, il considère la touche Entrée comme une validation.

Oui, ça je suis totalement d’accord. C’est pour cela que j’avais essayé de faire quelque chose du genre :

1
2
for i in range(nbLignes) :  
texte = input()

(j’arrive pas à mettre la tabulation)

Pour le dictionnaire, je n’en ai jamais utilisé mais j’en ai vaguement entendu parlé donc je ne suis pas sure de réussir à l’utiliser.

Oui, ça je suis totalement d’accord. C’est pour cela que j’avais essayé de faire quelque chose du genre :

Ici, le problème est en fait relativement simple. À chaque tour de boucle, tu stocke la valeur entrée par l’utilisateur dans la variable texte. Mais dès le second tour, l’ancienne valeur est écrasée par la nouvelle. Il faut donc sauvegarder le texte entré dans chaque tour de boucle dans une liste ou une string.

Par exemple, tu peux faire quelque chose comme ceci :

1
2
3
4
5
toutes_les_lignes = []
for i in range(nbLignes):
    cette_ligne = input()
    toutes_les_lignes.append(cette_ligne)
# "toutes_les_lignes" sera alors une liste de strings, chacune représentant une ligne.

(j’arrive pas à mettre la tabulation)

Oui, avec Markdown (le format de rédaction de message utilisé sur ZdS), il faut mettre des espaces (en général on en met 4), les tabulations ne sont pas supportées. ;)

Pour le dictionnaire, je n’en ai jamais utilisé mais j’en ai vaguement entendu parlé donc je ne suis pas sure de réussir à l’utiliser.

T’inquiètes pas, il y a aussi moyen de faire sans. Un indice : tu peux utiliser une liste de listes (quelque chose comme [["bonjour", 1], ["salut", 2], ["hello", 5]]). Je te réponds avec plus de détails dès que j’ai un moment. :)

+1 -0

Oui, avec Markdown (le format de rédaction de message utilisé sur ZdS), il faut mettre des espaces (en général on en met 4), les tabulations ne sont pas supportées. ;)

(Hors sujet) : Je vais chercher la petites bête, mais zmarkdown a l’air de supporter ça très bien en fait. C’est généralement les navigateurs web qui ne supportent pas ça (la principale raison doit être parce que ça rentre en conflit avec le déplacement du focus qui utilise généralement — lui aussi — la touche Tab). Donc généralement, une autre solution est de faire un copier-coller depuis un vrai éditeur de texte qui supporte les tabulations. Mais +1 pour les 4 espaces vu que c’est la norme officielle en Python.

+1 -0

Oui, avec Markdown (le format de rédaction de message utilisé sur ZdS), il faut mettre des espaces (en général on en met 4), les tabulations ne sont pas supportées.

(Hors sujet) : Je vais chercher la petites bête, mais zmarkdown a l’air de supporter ça très bien en fait. C’est généralement les navigateurs web qui ne supportent pas ça (la principale raison doit être parce que ça rentre en conflit avec le déplacement du focus qui utilise généralement — lui aussi — la touche Tab). Donc généralement, une autre solution est de faire un copier-coller depuis un vrai éditeur de texte qui supporte les tabulations. Mais +1 pour les 4 espaces vu que c’est la norme officielle en Python.

D’accord ! Donc je ferais les 4 espaces.

1
2
3
4
5
toutes_les_lignes = []
for i in range(nbLignes):
    cette_ligne = input()
    toutes_les_lignes.append(cette_ligne)
# "toutes_les_lignes" sera alors une liste de strings, chacune représentant une ligne.

Je repars donc avec ça. C’est vrai que c’est beaucoup mieux que ce que j’ai fait.

T’inquiètes pas, il y a aussi moyen de faire sans. Un indice : tu peux utiliser une liste de listes (quelque chose comme [["bonjour", 1], ["salut", 2], ["hello", 5]]

Je pense que je vais essayer ça.

Je te réponds avec plus de détails dès que j’ai un moment.

Aucun soucis c’est déjà super gentil de m’aider ! :D

C’est inefficace de compter les occurrences de chaque mot. Ça t’oblige à stocker 100 fois plus d’infos que nécessaire, et ça complique inutilement le code.

Pourquoi ne pas initialiser une liste (nb_mots) qui contient 25 fois 0 ? L’indice est le nombre de lettres du mot (25 est plus long que le mot le plus long de la langue française), et la valeur est un compteur.

Pour chaque mot du texte, nb_mots[len(mot)] += 1.

Et le tour est joué.

+0 -0

C’est inefficace de compter les occurrences de chaque mot. Ça t’oblige à stocker 100 fois plus d’infos que nécessaire, et ça complique inutilement le code.

Pourquoi ne pas initialiser une liste (nb_mots) qui contient 25 fois 0 ? L’indice est le nombre de lettres du mot (25 est plus long que le mot le plus long de la langue française), et la valeur est un compteur.

Pour chaque mot du texte, nb_mots[len(mot)] += 1.

Et le tour est joué.

nohar

Ouah, c’est simple et élégant. GG. :)

PS : Peut-être plutôt nb_mots[len(mot)-1] += 1 ou nb_mots.pop(0), pour éviter que le premier item soit vide ?

+0 -0

Bof ça coûte rien un item vide. Je suis partisan de ne pas en tenir compte, pour éviter de trimballer des -1 et des +1 dans le code au risque d’en oublier.

De toute façon dans la boucle qui te sert à restituer le resultat d’après l’énoncé il faut ignorer les indices pour lesquels il n’y a aucun mot, du coup ça ne crée même pas de cas particulier.

Autant ne pas se prendre la tête : un item supplémentaire à 0 ne coûte virtuellement rien en Python (par rapport au reste). La simplicité du code est bien plus importante.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte