Adloun

É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.