Écrire histogramme(effectifs, largeur) qui renvoie une liste de lignes…
Exercice d'entraînement · niveau 3 (difficile) · NSI (première), chapitre 5 — Les dictionnaires · Itérer, regrouper, comparer
Énoncé
Écrire histogramme(effectifs, largeur) qui renvoie une liste de lignes de texte : la clé, une barre de # proportionnelle, l'effectif. Les colonnes doivent être alignées.
Corrigé
def histogramme(effectifs, largeur=20):
"""Une ligne par cle : la cle, une barre proportionnelle, l'effectif.
Precondition : effectifs non vide, valeurs entieres >= 0, maximum > 0.
"""
assert len(effectifs) > 0
maxi = max(effectifs.values())
assert maxi > 0, "tous les effectifs sont nuls"
largeur_cle = max(len(str(c)) for c in effectifs)
lignes = []
for cle, n in effectifs.items():
barre = "#" * round(n * largeur / maxi)
lignes.append("%s | %-*s %d"
return lignes
Deux parcours, et il en faut deux. Le premier calcule le maximum et la largeur de la colonne des clés ; le second seulement construit les lignes. On ne peut pas tout faire d'un coup : la longueur de la première barre dépend d'un maximum qu'on ne connaîtra qu'après avoir tout vu.
La précondition « maximum ». Elle évite une division par zéro, mais surtout elle dit quelque chose de vrai : un histogramme d'effectifs tous nuls n'a pas de sens, la question de la proportion ne se pose pas.
Vérification.
lignes = histogramme({"a": 4, "b": 2, "c": 1}, largeur=8)
assert lignes[0] == "a | ######## 4"
assert lignes[1] == "b | #### 2"
assert lignes[2] == "c | ## 1"
assert len(set(len(l) for l in lignes)) == 1 # colonnes alignees
Le dernier assert vérifie l'alignement sans décrire chaque ligne : toutes ont la même longueur. C'est un test de propriété, plus robuste qu'une comparaison de chaînes — il resterait valable si l'on changeait le caractère de la barre.
Les autres exercices de ce chapitre Le cours du chapitre
Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.