logo

Les algorithmes diviser pour régner

Exercice 1 : tests d'efficacité

Nous allons comparer l'efficacité des 3 programmes suivants :

Nombre de boucles

Nous allons compter le nombre de boucles dans le pire des cas pour un tableau contenant un million de valeurs.

  1. Copiez et collez les 3 programmes et la ligne suivante :
    tab=list(range(1000000))
  2. Combien y aura-t-il de boucles dans l'approche naïve ?
  3. Dans les approches dichotomiques introduisez une variable etape qui permet de décompter le nombre de boucles.

    Voir une solution

  4. Testez ces fonctions avec les paramètres val = -1 et tab = tab.

Temps d'exécution

Nous alons utiliser le module timeit. Ce module fournit une façon simple de mesurer le temps d'exécution de fragments de code Python. Il expose une Interface en ligne de commande ainsi qu'une interface Python. Ce module permet d'éviter un certain nombre de problèmes classiques liés à la mesure des temps d'exécution.

Copiez, puis collez les lignes suivantes à la suite des 3 fonctions.

import timeit
liste=list(range(100))  #tester pour 200, 500
print(timeit.timeit('recherche_dichotomique(-1,liste)', globals=globals()))
print(timeit.timeit('recherche_dicho_liste(-1,liste)', globals=globals()))
print(timeit.timeit('recherche_naive(-1,liste)', globals=globals()))
  1. Testez avec les valeurs 100, 200 et 500.
  2. Analysez et commentez ces résultats.

Exercice 2 : Calcul de puissance

Approche naïve

L'écriture a**n permet de calculer des puissances. Naturellement cette écriture sera interdite dans cet exercice.

  1. Ecrire une fonction puissance de paramètres deux entiers naturels a et n et qui renvoie le nombre an.

    Voir une solution

  2. Combien de boucles sont nécessaire pour calculer puissance(2, 100) ?

Approche diviser pour régner

Voici un programme calculant la puissance utilisant la méthode diviser pour régner :

def exponentiationRapide(nombre,exposant):
    N = exposant
    A = nombre
    resultat = 1
    while N > 0 :
        if N % 2 == 0:
            A = A * A
            N = N // 2
        else :
            resultat = resultat * A
            N = N - 1
    return resultat

  1. Testez cette fonction avec différentes valeurs donnant des résultats connus.
  2. Faites tourner ce programme à la main pour nombre = 2 et exposant = 20.
  3. Introduisez une variable etape qui permet de décompter le nombre de boucles.

    Voir une solution

Tests d'efficacité

Copiez, puis collez les lignes suivantes à la suite des 2 fonctions.

import timeit
print(timeit.timeit('puissance(2,100)', globals=globals()))
print(timeit.timeit('exponentiationRapide(2,100)', globals=globals()))

Analysez et commentez ces résultats.

Pour aller plus loin

  1. Monrez la terminaison de la fonction exponentiationRapide en trouvant un variant de boucle.

    Voir une solution

  2. Montrez la correction de la fonction exponentiationRapide en utilisant l'invariant de boucle de « nombreexposant = resultat × AN ».

    Voir une solution