L2 MIASHS, Algorithme et Programmation 2, année 2021

TD 3

L’objectif de ce TP est d’approfondir les algorithmes en Diviser pour régner.

Les Points les plus proches

Le problème PointProches retourne les deux éléments d’une liste les plus proches.

Par exemple, pour la liste [0, 4, 5, 9, 15], la fonction PointProches retourne me couple (4, 5).

  1. Proposez une implémentation itératives naïve de ce problème.

  2. Proposez une implémentation diviser pour régner de ce problème.

Il pourra être nécessaire d’implémenter une fonction mediane qui prend une liste de nombre et qui retourne la médiane de la liste.

  1. Facultatif. (*) Proposez une implémentation diviser pour régner de la variante de ce problème ou la liste contient des nombres complexes.

  2. Facultatif. (**) Proposez une implémentation diviser pour régner de la variante de ce problème ou la liste contient des vecteurs de dimension \(d\).

L’algorithme de Karatsuba

Nous allons étudier comment l’algorithme de multiplication de nombres entiers réalisé par Python. Pour ce faire, dans cette partie, il est n’est pas autorisé d’utiliser de nombres entiers, nous allons manipuler uniquement des chaînes de caractères qui représentent des nombres.

Pour que cela soit plus simple, nous allons faire l’ensemble des calculs en décimal.

  1. Vérifier qu’une chaîne de caractère est un nombre.

Une chaîne de caractère représente un nombre correct s’il ne contient que des lettres qui représentent des chiffres décimaux (entre 0 et 9 donc). Écrire une fonction qui vérifie qu’une chaîne de caractères forme un nombre.

  1. Le successeur.

Le successeur d’un nombre \(n\) est le résultat de l’opération \(n+1\). Écrire une fonction successeur qui prend en argument une chaîne de caractères qui représente un nombre et retourne une chaîne de caractères qui représente son successeur.

Pour vous aider, on vous autorise à utiliser la fonction suivante:

def successor_chiffre(u):
    if len(u) > 1:
        raise ValueError("Interdit d'utiliser cette fonction pour des chaines trop grandes")
    return str(int(u)+1)
  1. L’addition.

Écrire une fonction addition qui prend en argument deux chaines de caractères qui représentent des nombres et qui retourne une chaîne de caractères qui réprésente leur somme.

La complexité connue pour l’addition est en \(O(n)\), si vous avez une complexité en \(O(n^2)\), essayez d’améliorer votre algorithme.

  1. La multiplication.

Écrire une fonction multiplication qui prend en argument deux chaines de caractères qui représentent des nombres et qui retourne leur produit.

La complexité d’un algorithme naïf pour la multiplication est en \(O(n^2)\), vérifier que c’est bien le cas!

  1. L’algorithme de Karatsuba.

En utilisant l’égalité suivante:

\[(a10^k + b)(c10^k + d)=ac10^{2k} + (ad+bc)10^k+bd\]

Proposez un algorithme en diviser pour régner pour la multiplication.

  1. Lire la complexité de cet algorithme sur la page wikipédia.

  2. Tracer la fonction \(n\mapsto n^{\log_2(3)}\) et comparer à la courbe du cours 1.