Adloun

Trouver, pour le système [6, 4, 1] , toutes les sommes de 1 à 50 pour…

Exercice de TD · niveau 3 (difficile) · NSI (première), chapitre 8 — Dichotomie, voisins et gloutons · Les algorithmes gloutons

Énoncé

Trouver, pour le système [6, 4, 1], toutes les sommes de à pour lesquelles le glouton n'est pas optimal. Y a-t-il une régularité ? Vérifier ensuite que le système européen n'a aucun défaut de ce genre.

Corrigé

Il faut d'abord savoir ce qu'est l'optimum — donc écrire une résolution exhaustive, qui essaie toutes les décompositions :


def optimal(somme, pieces):
    """Nombre MINIMAL de pieces, par exploration exhaustive."""
    meilleur = [None]

    def explorer(reste, i, n):
        if reste == 0:
            if meilleur[0] is None or n < meilleur[0]:
                meilleur[0] = n
            return
        if i >= len(pieces) or (meilleur[0] is not None and n >= meilleur[0]):
            return                       # elagage : cette branche ne peut plus gagner
        p = pieces[i]
        for k in range(reste // p, -1, -1):
            explorer(reste - k * p, i + 1, n + k)

    explorer(somme, 0, 0)
    return meilleur[0]

Le résultat, mesuré.


BIZARRE = [6, 4, 1]
manques = [s for s in range(1, 51)
           if len(rendu_monnaie(s, BIZARRE)) > optimal(s, BIZARRE)]
assert manques == [8, 9, 14, 15, 20, 21, 26, 27, 32, 33, 38, 39, 44, 45, 50]
assert len(manques) == 15

Quinze sommes sur cinquante — c'est le chiffre annoncé par la figure du cours, retrouvé ici par le calcul. Et la régularité saute aux yeux : les défauts vont par paires , , , …, espacées de . Les écarts successifs sont


ecarts = [manques[i + 1] - manques[i] for i in range(len(manques) - 1)]
assert ecarts == [1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5]

Pourquoi cette période . Le glouton prend une pièce de dès que la somme l'atteint ; il se trompe exactement quand deux pièces de auraient mieux valu, c'est-à-dire pour et — puis pour ces mêmes sommes augmentées d'un multiple de , où l'erreur se reproduit à l'identique après les pièces de prises au début.

Le système européen, lui, est canonique.


euro_manques = [s for s in range(1, 201)
                if len(rendu_monnaie(s, EURO)) > optimal(s, EURO)]
assert euro_manques == []

Aucun défaut sur les deux cents premières sommes. C'est une propriété du jeu de valeurs, pas de l'algorithme — et c'est bien pour cela que le glouton du rendu de monnaie « marche » dans la vie courante : les pièces ont été choisies pour, non l'inverse.

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.