XD blog

blog page

ensae, exercice, programmation, python


2013-12-14 Quelques exercices de préparation à l'examen (4)

On reprend le même texte que celui de l'exercice précédent. On veut connaître le nombre maximum de mots qu'on peut trouver entre deux mots commençant par une voyelle.

# source du texte : http://www.gutenberg.org/files/1567/1567-h/1567-h.htm#link2H_4_0017
texte = """They are rattling breakfast plates in basement kitchens,
And along the trampled edges of the street
I am aware of the damp souls of housemaids
Sprouting despondently at area gates.
The brown waves of fog toss up to me
Twisted faces from the bottom of the street,
And tear from a passer-by with muddy skirts
An aimless smile that hovers in the air
And vanishes along the level of the roofs.""".replace("\n"," ").lower().split()

def nombre_de_mot_maximum(mots) :
    ...
    return un_nombre 

Solution proposée

On utilise les fonctions de l'article précédent : 2013-12-11_nojs.html. L'énoncé de l'exercice est un peu ambigü : lorsqu'on cherche le nombre maximum de mots entre deux mots commençant par des voyelles, est-ce qu'on impose que ces mots commencent par des consonnes ou non ? C'est ce dernier cas que le programme suivant résoud (les commentaires contiennent la solution de premier cas, plus facile).

#coding:latin-1
# source du texte : http://www.gutenberg.org/files/1567/1567-h/1567-h.htm#link2H_4_0017
texte = """They are rattling breakfast plates in basement kitchens,
And along the trampled edges of the street
I am aware of the damp souls of housemaids
Sprouting despondently at area gates.
The brown waves of fog toss up to me
Twisted faces from the bottom of the street,
And tear from a passer-by with muddy skirts
An aimless smile that hovers in the air
And vanishes along the level of the roofs.""".replace("\n"," ").lower().split()

def est_voyelle(c):
    d = { "a":1, "e":1, "i":1, "o":1, "u":1, "y":1 }
    return d.get(c, 0)

def nombre_de_mot_maximum(mots) :
    # on transforme la liste de mots en liste de 0 ou 1 (0, consonne en première lettre, 1, voyelle)
    voyelle_pas_voyelle = [ est_voyelle(mot[0]) for mot in mots ]
    # on ajoute la position
    voyelle_pas_voyelle = [ (i,p) for i,p in enumerate(voyelle_pas_voyelle) ]
    # on ne garde que les positions avec des voyelles
    voyelle = [ c[0] for c in voyelle_pas_voyelle if c[1] == 1 ]
    # si le résultat souhaité est le nombre maximum de mots entre deux mots commençant par une voyelle
    # alors le résultat est : return voyelle[-1] - voyelle[0]
    # si le résultat souhaité est le nombre maximum de mots commençant par une consonne entre deux mots commençant par une voyelle
    # alors le résultat est :
    diff = [ voyelle[i] - voyelle[i-1] for i in range(1,len(voyelle)) ]
    return max(diff)
    
print ( nombre_de_mot_maximum(texte) )  # affiche 8

Question : à quoi sert la ligne suivante (ligne 21) ?

# on ajoute la position
voyelle_pas_voyelle = [ (i,p) for i,p in enumerate(voyelle_pas_voyelle) ]

L'objectif de l'exercice est de trouver le nombre maximum de mots entre deux autres mots. Comment compter ces mots ? Comment savoir combien il y a de mots entre deux autres mots ? Une façon simple de faire est de considérer leurs positions : si je prends deux mots au hasard dans le texte qui ont pour positions p et q, la différence de leur position est exactement le résultat cherché, soit p-q (ou p-q-1 selon qu'on inclut ou non le premier mot). C'est illustré par la figure suivante (extraite de Python Tutor) :

En haut, la liste des mots. En bas, on a remplacé les mots par 0 s'il commence par une consonne, 1 si c'est par une voyelle. Si je compte le nombre de zéros entre deux 1 consécutifs, j'obtiens un nombre de mots commençant par une consonne entre deux mots commençant par une voyelle.

A partir de moment là, il est possible de conserver une liste de 0 ou de 1 ou de garder les positions des seuls éléments 1 comme suit :

Mais pour ce faire, il faut à un moment ou à un autre considérer les éléments (0ou 1) et leurs positions. D'où la fonction enumerate à la ligne 21.


<-- -->

Xavier Dupré