T1.b copier des listes : ATTENTION


Copier une liste


Cette section est particulièrement importante et doit être bien comprise

Example: Copier une liste ? ATTENTION !

Vous voyez que la modification de x modifie y aussi ! 
Dans python tutor ( cliquer sur visualiser pour acceder à python tutor) vous pouvez voir que x=y n'a pas dupliqué la liste.

Techniquement, Python utilise des pointeurs (comme dans le langage de programmation C) vers les mêmes objets. Python Tutor l'illustre avec des flèches qui partent des variables x et y et qui pointent vers la même liste. Donc, si on modifie la liste x, la liste y est modifiée de la même manière. Rappelez-vous de ceci dans vos futurs programmes car cela pourrait avoir des effets désastreux !

Pour éviter ce problème, il va falloir créer une copie explicite de la liste initiale. Observez cet exemple :

Example: Copier une liste ? ATTENTION !

Si on regarde à nouveau dans Python Tutor (Figure 12), on voit clairement que l'utilisation d'une tranche [:] ou de la fonction list() crée des copies explicites. Chaque flèche pointe vers une liste différente, indépendante des autres

Attention, les deux techniques précédentes ne fonctionnent que pour les listes à une dimension, autrement dit les listes qui ne contiennent pas elles-mêmes d'autres listes.

Example: Copier une liste ? ATTENTION !
Example: Avec deepcopy

T1.3 Révisions : Algorithmes à connaitre

Algorithmes de tris et dichotomie


Premier algo


fonction algo1(tableau) : 
pour i allant de 0 à longueur(tableau)-2 :
imin=i
pour j allant de i+1 à len(tableau)-1 :
si tableau[j] < tableau[imin] :
imin=j
fin de si
fin de pour
if imin!=i:
tableau[i],tableau[imin]=tableau[imin],tableau[i]
fin de si
renvoyer tableau
Multiple Choice Exercise
L'algorithme ci-dessus correspond à ...
Correct!
Coding Exercise: ALGO 1
Coder le pseudo code donné au dessus.
Une liste lst sera générée pour vous pour la validation.
Dans la fonction, vous introduirez un comptage du nombre de comparaisons effectuées, qui sera affiché avant de sortir de la fonction (comme indiqué dans le code à compléter ci-dessus)

Deuxième algo


fonction algo2(lst) : 
pour i de 1 à len(lst) - 1 # mémoriser lst[i] dans x x ← lst[i] # décaler vers la droite les éléments de lst[0]..lst[i-1] qui sont plus grands que x en partant de lst[i-1] j ← i tant que j > 0 et lst[j - 1] > x lst[j] ← lst[j - 1] j ← j - 1 fin de tant que # placer x dans le "trou" laissé par le décalage lst[j] ← x renvoyer lst
Multiple Choice Exercise
L'algorithme ci-dessus correspond à ...
Correct!
Coding Exercise: ALGO 2
Coder le pseudo code donné au dessus.
Une liste lst sera générée pour vous pour la validation.
Dans la fonction, vous introduirez un comptage du nombre de comparaisons effectuées, qui sera affiché avant de sortir de la fonction (comme indiqué dans le code à compléter ci-dessus)

Comment interpréter les nombres de comparaison des algorithmes 2 et 3 ?

Pouvez vous donnez le nombre de comparaisons de l'algo 1 pour une liste de 200 valeurs ?

Pour l'algo2, que pourrait on dire ?

Et quelle est la complexité de l'algo 3 ?


Troisième algo


fonction algo3(x,lst) :
imin=0 imax=len(lst)-1 imilieu=(imin+imax)//2 tant que imin <= imax : si lst[imilieu]>x # on va chercher dans la partie de gauche : imax=imilieu-1 sinon si lst[imilieu] < x : # on va chercher dans la partie de droite: imin=imilieu+1 sinon : # on a trouvé x renvoyer True fin de si imilieu=(imin+imax)//2 fin de tant que renvoyer False
Multiple Choice Exercise
L'algorithme ci-dessus correspond à ...
Correct!
Coding Exercise: ALGO 3
Coder le pseudo code donné au dessus.
Une liste lst sera générée pour vous pour la validation.
Dans la fonction, vous introduirez un comptage du nombre de comparaisons effectuées, qui sera affiché avant de sortir de la fonction (comme indiqué dans le code à compléter ci-dessus)

S'il vous reste du temps...

Modulo 7

Voici un graphe (nous étudierons les graphes plus en détail bientôt) qui permet de calculer N%7 pour tout nombre entier N :

Ce graphe contient des flèches noires et des flèches bleues. Votre premier travail est de modéliser le graphe avec deux dictionnaires : BLACK et BLUE.

Dans chacun des dictionnaires, les clés sont les valeurs de départ des flèches (noires ou blueues) et les valeurs sont les valeurs d'arrivée.

Par exemple, dans le dictionnaire NOIR, la clé 0 à pour valeur 1.

Ensuite, vous devez implementer l'algorithme de détermination de N%7. Etudions un exemple :


Coding Exercise: Graphe Modulo 7

T1.a - Révisions cours : les listes

I Principales méthodes de manipulation des Listes

Nous avons utilisé les listes très fréquemment et nous allons rapidement revoir les principales méthodes associées aux objets de type list.

Comme pour les chaînes de caractères, les listes possèdent de nombreuses méthodes qui leur sont propres et qui peuvent se révéler très pratiques. On rappelle qu'une méthode est une fonction qui agit sur l'objet auquel elle est attachée par un point. Nous étudierons la programmation orientée objet (POO) très prochainement.


AJOUTER : .append et .insert


La méthode .append(), ajoute un élément à la fin d'une liste tandis que La méthode .insert() insère un objet dans une liste avec un indice déterminé :

Example: mince ! j ai oublié mon d


LOCALISER, COMPTER : .index et .count


La méthode .count() compte le nombre d'éléments (passés en argument) dans une liste :
La méthode .index() donne la position d'un élément dans une liste.

Example: Combien de a dans 'abracadabra' ?


TRIER : .sort et .sorted et aussi reverse


La méthode .sort() trie une liste en laissant les valeurs triées dans cette liste tandis que  .sorted() renvoie une copie de la liste triée

Example: trier en place ou pas ?


SUPPRIMER : del remove pop


Example: suppression d'élément avec remove
Example: suppression d'élément : la fonction del
Example: suppression d'élément : la méthode pop

Construction d'une liste par itération

La méthode .append() est très pratique car on peut l'utiliser pour construire une liste au fur et à mesure des itérations d'une boucle.

Pour cela, il est commode de définir préalablement une liste vide de la forme maliste = []. Voici un exemple où une chaîne de caractères est convertie en liste :

Example: contruction par itération

La méthode avec list(seq) est certes plus simple, mais il arrive parfois qu'on doive utiliser des boucles tout de même, comme lorsqu'on lit un fichier. On rappelle que l'instruction list(seq) convertit un objet de type chaîne de caractères en un objet de type liste. De même que list(range(10)) convertit un objet de type range en un objet de type list ou encore list(dic.keys()) converti la liste des clés d'un dictionnaire en un objet de type liste.


Appartient : in


Example: test d'appartenance

Autres méthodes utiles


Le type liste de python dispose de méthodes supplémentaires par rapport à ce qui précède. Voici toutes les méthodes des objets de type liste :

  • list.extend(iterable)
    Étend la liste en y ajoutant tous les éléments de l'itérable. Équivalent à a[len(a):] = iterable.
  • list.clear()
    Supprime tous les éléments de la liste. Équivalent à del a[:].
  • list.index(x[, start[, end]])
    Renvoie la position du premier élément de la liste dont la valeur égale x (en commençant à compter les positions à partir de zéro). Une exception ValueError est levée si aucun élément n'est trouvé. Les arguments optionnels start et end sont interprétés de la même manière que dans la notation des tranches et sont utilisés pour limiter la recherche à une sous-séquence particulière. L'indice renvoyé est calculé relativement au début de la séquence complète et non relativement à start.

T - 4.2 Listes

Dans cette partie nous utiliserons donc ce jeu de primitives :

listeVide (): renvoie une LISTE vide
estListeVide (l) : renvoie True si l est une LISTE vide, False sinon
cons(x,l) : renvoie une nouvelle LISTE égale à l plus l'élément x ajouté en tête
listeQueue(l) : renvoie la queue de l
listeTete(l) : renvoie la tête de la LISTE

et nous ajouterons une première fonction dérivée des primitives de base :
longueur(l) : renvoie la longueur de la LISTE l

Le type des objet ainsi créés est nommé LISTE

une première implémentation

Example: Type abstrait LISTE

Complexité

Multiple Choice Exercise: Complexité de la fonction cons :
le nombre d'instructions requis pour cette fonction est :
Correct!
Multiple Choice Exercise: Complexité de la fonction longueur :
le nombre d'instructions requis pour cette fonction est :
Correct!

Une seconde implémentation

Bon, il est possible que notre représentation avec les tuples imbriqués ne vous plaise pas beaucoup... non ? En fait ceci n'est qu'une affaire de notation, et n'a pas grande importance. Dans l'exemple ci-dessous, nous allons modifier le constructeur pour changer la représentation de nos LISTE mais nous ne changeons pas les autres primitives (sauf listeQueue de façon marginale), et pas plus la fonction dérivée longueur, et tout fonctionne de façon identique :

Example: Type abstrait LISTE version 2

Notez bien que, malgré l'implémentation un peu différente, les appels aux primitives sont strictement identiques (le programme principal est strictement identique, la fonction longueur également).

La représentation est bien la même, nous avons seulement affecté la notation.
Dans la suite, nous utiliserons cette version, qui donne un affichage plus lisible, mais pour autant, ne perdez pas de vue que nos LISTE sont toujours une tête et une queue.

POO - Bilbo et Golum

A vous : programmez le combat

Coding Exercise: combat à mort
Modifiez de nouveau le code, cette fois la méthode perdVie doit être écrite de façon à ne jamais renvoyer un nombre de vie négatif. Si le nombre de vie est négatif, nombre de vie sera mis à 0.. Vous devez :
  1. Modifiez perdVie pour ne jamais renvoyer un nombre de vie négatif.
  2. Completer le code de façon à créer 2 personnages ayant 100 vies.
  3. Vous initialiserez une variable attaquant qui vaut 0 ou 1. Si elle est égale à 0, c'est Bilbo qui attaque en premier, sinon c'est Golum. A la fin de chaque attaque, la variable attaquant prendra la valeur 1-attaquant.
  4. A la fin du combat affichez le nombre d'attaques qui ont eu lieu.

T - 4 - Implémenter les graphes

Comme les listes, les piles, et les files, il est important de distinguer le type abstrait de représentation des données, du type implémenté dans le langage.

En Python il n'existe pas de type GRAPHE prédéfini. C'est donc à chacun de l'implémenter avec les outils disponibles dans le langage.

Comme pour les listes il peut exister, selon les auteurs, des différences sur le nombre et la définition des primitives de bases. Nous allons utiliser ici ce jeu de primitives :

  • creerGrapheVide() : retourne un graphe vide
  • estVideGraphe(G) : retourne True si G est un graphe vide
  • ajouterSommet(G,s) : retourne le graphe après ajout du sommet s
  • supprimerSommet(G,s) : retourne le graphe après suppression du sommet s (et tout les arcs rliés à s)
  • existeSommet(G,s) : retourne True si s est un sommet du graphe G
  • Pour un graphe orienté :
    • ajouterArc(G,sd,sa) : retourne le graphe après ajout d'un arc reliant sd à sa (orienté)
    • supprimerArc(G,sd,sa) : retourne le graphe après suppression de l'arc sd->sa
    • existeArc(G,sd,sa) : retourne True si sd->sa est un arc du graphe G
  • Pour un graphe non orienté :
    • ajouterArete(G,sd,sa) : retourne le graphe après ajout d'une arête reliant sd à sa (non-orienté)
    • supprimerArete(G,sd,sa) : retourne le graphe après suppression de l'arête sd->sa
    • existeArete(G,sd,sa) : retourne True si sd->sa est une arête du graphe G

Une première implémentation (d'un graphe orienté) avec un dictionnaire

Comme nous l'avons vu, un graphe peut être représenté par une liste de successeur. Cette représentation peut être implémentée efficacement avec un dictionnaire. Chaque sommet sera donc une clé dictionnaire, et sa valeur sera la liste des sommets sa reliés à s dans le sens s -> sa.

En conséquence, un graphe vide est un dictionnaire vide.

Example: implémentation des graphes avec un dictionnaire

Premier exemple d'implémentation d'un graphe, en utilisant une liste de dictionnaire dont les clés sont les sommets et les valeurs les listes de successeurs des sommets.

T-1.2 - Revisions : modéliser une situation

Les listes

Définition : conteneur regroupant des éléments, ordonnés, repérés par un indice.

exemples : lst = [ 1, 2, 3 ] lst=["a" , "b" , "c" ] lst = [1, [2,3], "abc" ] etc..

Accès ou modifier des éléments :

lst = [1, 2, 3, 4, 5, 6]
lst[0] vaut 1  lst[3] vaut 4
lst[2:4] vaut [2, 3, 4]
lst[:3] vaut [1, 2, 3] 
lst[3:] vaut [4, 5, 6]
pour modifier : lst[2] = 10 -> lst vaut [1, 2, 10, 4, 5, 6]

Parcourir

Parcours sur les éléments :
lst = [1, 2, 3, 4]
for elem in lst :
    print(elem)
affichera :
1
2
3
4

Parcours sur les indices :
lst = [1, 2, 3, 4]
for i in range(len(lst)) :
    print(lst[i])
affichera le même résultat

méthodes

Ajouter un élément :

Avec append :
lst = [1, 2, 3, 4]
lst.append(5) -> lst vaut [1, 2, 3, 4, 5]

Avec insert : 
lst = [1, 2, 3, 4]
lst.insert(0, "A") -> lst vaut ["A", 1, 2, 3, 4]
Retirer un élément :

Avec pop:
lst = [1, 2, 3, 4]
lst.pop() -> renvoie 4 et lst vaut [1, 2, 3]
lst.pop(0) -> renvoie 0 et lst vaut [2, 3, 4]
lst.pop(1) -> renvoie 2 et lst vaut [1, 3, 4]

Avec remove: 
lst = [1, 2, 3, 4]
lst.remove(1) -> lst vaut [2, 3, 4] (erreur si élément non présent)

avec del :
lst = [1, 2, 3, 4]
del lst[1] -> lst vaut  [1, 3, 4] (retire l'élément d'indice 1)
trier :

Avec sort():
lst = [6, 2, 7, 4]
lst.sort() -> ne renvoie rien et modifie lst qui vaut [2, 4, 6, 7]


Avec sorted: 
lst = [6, 2, 7, 4]
sorted(lst) renvoie une nouvelle liste contenant : [2, 4, 6, 7]
en général utilisé ainsi :
lst2 = sorted(lst1)
divers

count():
lst = [6, 2, 7, 4, 2, 1, 2]
lst.count(2) -> renvoie 3 (2 est trois fois dans la liste)

index() :
lst.index(2) renvoie 1 (la première occurrence de  2 est à l'indice 1)
index renvoie une erreur si l'élément n'est pas présent

Initialiser et remplir une liste

Exemple : créer une liste contenant les entiers de 1 à 10 :

Avec liste vide et append :
lst = []
for i in range(1, 11) :
    lst.append(i)

Avec une initialisation à la bonne longueur (ici, 10 éléments) :
lst = [0]*10 (créé une liste contenant 10 fois l'entier 0)
for i in range(1, 11) :
    lst[i] = i

Exercices

Les algo simples

Tirage du Loto

Coding Exercise: Loto
Vous devez générer une liste contenant les entier de 1 à 49. Ensuite, votre code doit tirer, sans remise, 6 numéros qu'on stocke dans une liste, puis, toujours sans remise, un dernier numéro (le numéro complémentaire).
 

CONTRAINTE : Vous ne devez pas utiliser random.choice() même si vous connaissez cette fonction du module random.
 
APPROFONDIR : Envisagez différente façon de coder ce problème, utilisant pop() del ou remove()....
 
Votre code affichera la liste des 6 numéros puis le complémentaire comme ceci :
[31, 3, 12, 45, 13, 27]
18

Doublons

Coding Exercise: DOUBLONS
Soit la liste de nombres liste = [5, 1, 1, 2, 5, 6, 3, 4, 4, 4, 2]. A partir de liste, créez une nouvelle liste sans les doublons, et affichez-la.

Nombre mystère

Coding Exercise: Nombre mystère
Trouvez le nombre mystère qui répond aux conditions suivantes :

  • Il est composé de 3 chiffres.
  • Il est strictement inférieur à 300.
  • Il est pair.
  • Deux de ses chiffres sont identiques.
  • La somme de ses chiffres est égale à 7.

On vous propose d'employer une méthode dite « brute force », c'est-à-dire d'utiliser une boucle et à chaque itération de tester les différentes conditions.

Les indispensables (donc vous ne pouvez PAS vous en dispenser)

Recherche min/max (curseur)

Voila un algorithme qui intervient dans de nombreux autres. Vous en connaissez au moins un cas....
Dans ce type d'algorithme on parcourt une liste en conservant l'index correspondant à un critère.

On pourrait sans peine changer un peu le problème en : trouver la dernière valeur paire, trouver le dernier mot commençant par Z etc...

Coding Exercise: Maximum
Créez une fonction idxMax() qui prend comme argument une liste d'éléments ordonnables et renvoie l'indice du plus grand.
 
CONTRAINTE : vous ne devez pas utiliser la fonction max de python, le but est de la reprogrammer !
 
Quelle est la complexité de cet algorithme ?

Dans l'exercice ci-dessus, on veut l'indice du max.

Il est crucial de ne pas mélanger INDICE et VALEUR, c'est souvent la cause d'erreurs dans les exercices. On lit souvent des choses comme :

def get_idx_min(lst) :
    """ lst liste non vide"""
    min = 0                     # min est le premier INDICE
    for elem in lst :           # parcours sur les VALEURS
        if elem < min:          # on compare 1 VALEURS et un INDICE ! c'est incorrect
                   min = elem   # maintenant min devient une valeur
    return min

Compter sur un critère (compteur)

La notion de compteur est fondamentale. Dans \"Compter le nombre de <un truc> \" le mot qui importe est compter.

Coding Exercise: Un compteur sachant compter doit savoir compter sans compter
Créez une fonction compter(lst) qui renoie le nombre de multiples de 3 dans la liste lst.

moyenne des éléments pairs (compteur + accumulateur)

Les accumulateurs et les compteurs sont des pièces maitresse que vous ne pouvez pas ignorer. Voici deux cas basiques d\'utilisation de ceux ci, le compteur pour la moyene (diviser par le nombre de valeurs) et l'accumulateur pour faire la somme.
Coding Exercise: moyenne et somme
Créez une fonction somme(lst) et une autre moyPairs(lst) qui prennent comme argument une liste de nombre et renvoient l'une la somme de tous les éléments, l'autre la moyenne des éléments pairs de la liste.

Manipulation et parcours de chaînes

Rappels

chaine = "abcdefabcdef"

Portion de chaine :
chaine[0] vaut "a"
chaine[2:4] vaut "cd"
chaine[:3] vaut "abc"
chaine[2:] vaut "cdefabcdef"
chaine[-1] vaut "f"

Fonctions et méthodes :
longueur : len(chaine) vaut 12
a.find('c') renvoie 2   et a.find('z') renvoie -1
a.replace('a','A') renvoie 'AbcdefAbcdef' et a.replace('a','A',1) renvoie 'Abcdefabcdef'
a.upper() renvoie 'ABCDEFABCDEF'   et 'ABCDEF'.lower vaut 'abcdef'
"a et b".split(" ") renvoie ["a","et","b"]
"a et b, sont 2 nombres".split(",") renvoie ["a et b","sont 2 nombres"]

Parcourir :
for lettre in chaine :
    print(lettre)

Exercice

Coding Exercise: Retourner une chaine
Ecrire une fonction reverse_str correspondant aux spécifications ci-dessus.

Les dictionnaires

Définition : conteneur regroupant des éléments, non ordonnés, repérés par une clé (t-uplet nommé).

Les clé jouent le même rôle que les indices des listes

exemples :
dico = { 1: 1, 2:2, 3:3 } # les clé sont des int, la valeurs aussi
dico ={"cle1":2 , "cle2" : 3, "cle3":4 } # les clés sont des str, les valeurs sont int
eleve = { "nom": "Dupond" , "prenom" : "Jean" , "age":15 } # les clés sont str, les valeurs sont de type str ou int

Accès ou modifier des éléments :

eleve = {"nom": "Dupond" , "prenom" : "Jean" , "age":15}
accéder : 
eleve["nom"] vaut "Dupond"
eleve["age"] vaut 15
eleve[0] n'existe pas, il n'y a pas de clé 0 -> KeyError

modifier : 
eleve["nom"] = "Durand" modifie la valeur de la clé nom

méthodes

Ajouter un élément :

Contrairement aux listes, on n'utilise pas une méthode.
On définit simplement une nouvelle clé :
eleve = { "nom": "Dupond" , "prenom" : "Jean" , "age":15 }
Pour ajouter la clé classe :
eleve["classe"] = "TG8"

Retirer un élément :

on utilise del :
eleve = { "nom": "Dupond" , "prenom" : "Jean" , "age":15 }
del eleve["age"] -> eleve vaut {"nom": "Dupond" , "prenom" : "Jean"}
trier : on ne trie pas un dict

divers

keys():
eleve = { "nom": "Dupond" , "prenom" : "Jean" , "age":15 }
eleve.keys() renvoie ["nom" , "prenom" , "age"]
ça ressemble à une liste, ce n'en est pas tout à fait une mais on peut l'utiliser comme une liste.

values() :
eleve = { "nom": "Dupond" , "prenom" : "Jean" , "age":15 }
eleve.values() renvoie ["Dupond" , "Jean" , 15]

items() :
eleve = { "nom": "Dupond" , "prenom" : "Jean" , "age":15 }
eleve.items() renvoie [("nom","Dupond") , ("prenom","Jean") , ("age",15) ]
c'est une liste de tuples.

Initialiser et remplir un dict

Exemple : créer notre élève :

eleve = {}
eleve["nom"] = "Dupond"
eleve["prenom"] = "Jean"
eleve["age"] = 15

Parcourir

Parcours sur les clés (de loin le plus fréquent):
eleve = {"nom": "Dupond", "prenom" : "Jean", "age":15 }
for cle in eleve.keys() :
     print("la cle est : ", cle," sa valeur est:", eleve[cle])
affichera :
la cle est : nom sa valeur est: Dupond
la cle est : prenom sa valeur est: Jean
la cle est : age sa valeur est: 15

comme le parcours sur les clés est fréquent on peut écrire :
for cle in eleve :
    print("la cle est : ", cle, " sa valeur est:", eleve[cle])
qui fera la même chose.

Parcours sur les valeurs (assez rare et peut poser problème, on ne sait pas retrouver les clés):
for val in eleve.values() :
    print(" la valeur est:", val)

peut être utilisé quelques fois. Exemple :
ventes = {"geoffroy":12 , "arnaud" : 13 , "gilles":16 , "jean" : 5}
def moyenne_ventes(ventes) : 
   total = 0
   for val in ventes.values() : 
       total += val
   return total / len(ventes)

Mais souvent on préfèrera itérer quand même sur les clés :
def moyenne_ventes(ventes) :
    total = 0
    for cle in ventes.keys() :
        total += vente[cle]
    return total / len(ventes)


Parcours sur les items:
for item in eleve.items() :
    print(item)
affichera :
('nom', 'Dupond')
('prenom', 'Jean')
('age', 15)

Exercices un peu plus élaborés utilisant listes, chaines et dictionnaires

Le paradoxe du Duc de Toscane

Coding Exercise: Le paradoxe du Duc

Votre code affichera le résultat avec les pourcentages arrondis à 0.01 près sous cette forme :
fréquence de 9 : 11.5
fréquence de 10 : 12.81

Triangle de Pascal

Coding Exercise: Le triangle de Pascal
Voici le début du triangle de Pascal :

  1. 1
  2. 1 1
  3. 1 2 1
  4. 1 3 3 1
  5. 1 4 6 4 1.
  6. 1 5 10 10 5 1
  7. [...]

Vous représenterez chaque ligne par une liste.
Ainsi la ligne 1 est représentée par [1], la ligne 2 par [1, 1], etc...
Déduisez comment une ligne est construite à partir de la précédente.
Par exemple, à partir de la ligne 2 : [1, 1], construisez la ligne suivante (ligne 3 : [1, 2, 1]) et ainsi de suite.
Implémentez cette construction en Python en créant une fonction.
Ecrire le programme pour qu'il affiche les 20 premières lignes du triangle de Pascal

Des listes, des chaines, des dictionnaires
(application en bio-informatique)

Séquence d'ADN

Coding Exercise: Un brin d'ADN
Créez une fonction seq_alea() qui prend comme argument un entier positif taille représentant le nombre de bases de la séquence et qui renvoie une séquence d'ADN aléatoire sous forme d'une liste de bases. (c'est à dire une liste contenant uniquement les éléments "A" "T" "C" ou "G").
 
Utilisez la méthode .append() pour ajouter les différentes bases à la liste et la fonction random.choice() du module random pour choisir une base parmi les 4 possibles.
 
Aide!

Séquence d'ADN complémentaire inverse

Rappel : les dictionnaires sont des structures de données qui utilisent des clés au lieu des indices.

dico={"NOM":"LOVELACE" , "Prénom" : "Ada"} est un dictionnaire.

  • "NOM" et "Prénom" sont les clés
  • "LOVELACE" et "Ada" sont les valeurs associées à ces clés.
  • ("NOM" : "LOVELACE") est un elément du dictionnaire.

Par exemple :

Example: Objets géométriques

 

Application :

dans l'exercice ci-dessous, la structure de donnée dictionnaire est bien adaptée. A vous de jouer !

Coding Exercise: Brin d'ADN complémentaire
Créez une fonction comp_inv() qui prend comme argument une séquence d'ADN sous la forme d'une chaîne de caractères, qui renvoie la séquence complémentaire inverse sous la forme d'une autre chaîne de caractères
 
Par exemple, la chaine complémentaire inverse de AACGCT est TTGCGA :

  • les A sont changés en T et inversement
  • les C en G et inversement.


 
CONTRAINTE : vous devez utiliser un dictionnaire dont les clefs sont les bases ATCG et les valeurs, les bases de remplacement de chaque clef.
Votre code ne doit contenir aucun test.
 
 
Aide 1! Aide 2!

Séquence d'ADN aléatoire 2 (Approfondissement)

Dans cet exercice vous allez avoir besoin de random.shuffle(). Voici un exemple de l'utilisation de cette méthode :

Example: à en perdre son latin...

En utilisant étudiant l'exemple ci-dessus, pour bien comprendre le fonctionnement de la méthode .shuffle, vous pouvez aborder l'exercice ci-dessous :

Coding Exercise: ADN aléatoire contraint
Créez une fonction seq_alea_2() qui prend comme argument 4 entiers représentant respectivement la longueur de la séquence et les pourcentages de chacune des 3 bases A, T et G (le pourcentage de C etant alors déterminé). La fonction générera aléatoirement une séquence d'ADN qui prend en compte les contraintes fournies en arguments et renverra la séquence sous forme d'une liste. Utilisez cette fonction pour générer aléatoirement une séquence d'ADN de 50 bases contenant 10 % de A, 30 % de T, 50 % de G et 10 % de C. Conseil : la fonction random.shuffle() du module random vous sera utile.

Les listes de listes : lignes, colonnes et diagonales

Exemple

Ce sont des listes, dont les éléments sont des listes. Les sous listes peuvent contenir des éléments de types quelconques (numériques, string etc...)

lst = [[11,12,13], [21, 22, 23], [31 , 32, 33]]

lst[1] vaut [21, 22, 23]
et donc :
lst[1][0] vaut 21 (l'élément d'indice 0 dans lst[1])

lignes, colonnes et diagonales

parcourir la liste de liste et afficher les lignes :

lst = [[11,12,13], [21, 22, 23], [31 , 32, 33]]

# parcours sur les indices :
for num_ligne in range(len(lst)) :
    print(lst[num_ligne])

# on aurait put faire un parcours sur les éléments:
for ligne in lst :
    print(ligne)
afficher les colonnes:

lst = [ [11,12,13] , [21, 22, 23] , [31 , 32, 33] ]

les colonnes ne correspondent pas à un élément de la liste
mais peuvent être reconstituées en piochant dans les éléments des
sous listes :
colonne1 = [lst[0][1], lst[1][1], lst[2][1]]

ce n'est pas très joli ! on préfère :
colonne[num_col] = [lst[i][col] for col in range(3)]

afficher la diagonale 1 (en haut à gauche à en bas à droite):

| X  .  . |
| .  X  . |
| .  .  X |
lst = [[11, 12, 13], [21, 22, 23], [31 , 32, 33]]

diag1 = [lst[i][i]  for i in range(3)]


afficher la diagonale 2 (en haut à droite à en bas à gauche):

| .  .  X |
| .  X  . |
| X  .  . |
lst = [[11,12,13], [21, 22, 23], [31 , 32, 33]]

diag2 = [lst[i][2 - i]  for i in range(3)]

plus généralement, pour un tableau carré de taille n :
col = [lst[i][col] for i in range(n)]
diag1 = [lst[i][i] for i in range(n)]
diag2 = [lst[i][n - i] for i in range(n)]

Les listes de dict

A venir ultérieurement

1ere - Traitements des chaines de caractères

Le maniement des chaînes de caractères est important dans de nombreuses situations :

  • Extraire une information d'un texte.
  • Formater une chaîne pour un affichage lisible.
  • des algorithmes divers, comme par exemple celui permettant de proposer un mot lorsque l'utilisateur tape les premières lettres, ou des correcteurs ortographiques etc..
Accéder à un caractère dans la chaîne

Les chaînes sont en réalité des listes de caractères, et peuvent être traitée comme des listes : Les caractères sont repérés par leur indice :

Indice0123456789101112
caractèreHello,World!
correspondance caractère <-> indice

Notez que le caractère à l'index 6 est un espace.

Example: Extraire un caractère d'une chaîne

Longueur d'une chaîne
Example: Longueur d'une chaîne
sous chaîne
Example: Sous chaîne
Afficher une sous chaine
Coller des chaînes: +

Nous savons tous que 1+2=3.

Avec les chaînes, nous obtenons le résultat suivant à la place:"

Example: Sous chaîne
Concatenation

Attention : On ne peut additionner que des éléments de même type

Example: TypeError
Exécutez ce code et prendre note de l'erreur de type, que vous rencontrerez souvent et que vous devez comprendre.
TypeError: unsupported operand type(s) for +: 'int' and 'str'
Donne plusieurs informations :

  • TypeError indique qu'on a effectué une opération entre deux types imcompatibles
  • for + indique l'opération en cause, ici c'est l'opérateur +
  • int and str : les 2 opérandes sont : le premier un entier, le second une chaîne
Conversions de chaînes: +

Conversion de chaine de caractères

Comme vous le savez déjà, nous pouvons convertir une chaine de caractères en entier et inversement.

Pour cela, nous utilisons les fonctions str() et int().

Example: int et str
Exécutez ce code.

Mais nous pouvons aussi convertir une chaîne en liste :

Example: str en liste
Exécutez ce code.

quelques compléments pour utiliser print

On a parfois besoin d'afficher successivement plusieur texte, sans passer à la ligne. Cela est possible en utilisant, dans la fonction **print**, l'option end=""

Example: exemple sans end=..
Exécutez et observez

Ajoutons l'option end = ""

Example: avec end=""
Exécutez et observez

ou end = " "

Example: avec end=" "
Exécutez et observez

Exercices

Niveau 1


Fonction repeteMot

Coding Exercise: Le perroquet
Ecrire une fonction qui répète un même mot un certain nombre de fois au choix.

Il y aura donc 2 arguments : une valeur numérique et un mot.
Ex: Repete(3,"Ok") affichera "OkOkOk"
La fonction ne renvoie rien, elle affiche simplement.

CONTRAINTE :Vous ne devez pas utuliser de concaténation, seulement avec l'option end=..

Parcours de chaîne

Example: parcours de chaîne SUR LES INDICES
Parcours de chaine (sur les indices)
Example: parcours de chaîne
Parcours sur les caractères

Pour éviter de vous tromper :

Nommez l'itérateur soigneusement l'iterateur :

  • i pour un parcours avec les indices : for i in range( len(lst) ) :
  • caractère (ou lettre) pour un parcours sur les caracteres : for caractere in txt :

Ces deux façons de procéder se retrouvent pour tout les itérables. Un itérable est un type de variable contenant des éléments. Par exemple, les chaînes de caractères, et les listes, sont des itérables : on peut itérer sur les lettres d'un mots, sur les éléments d'une liste etc....

Nous retrouveront donc les mêmes parcours pour les listes, et pour bien d'autres structures plus tard.

exercice avec parcours de chaines

Coding Exercise: Première occurence
En étudiant l'exemple précédent, vous pouvez écrire une fonction search(lettre : str,txt:str) qui parcours la chaîne txt et qui renvoie un entier correspondant à l'indice de la première occurrence du caractère lettre dans txt.

Si la lettre n'est pas trouvée, la fonction doit renvoyer -1.
Aide 1 Aide 2
Modifiez pour que la fonction renvoie la dernière occurrence (au lieu de la 1ere)
Coding Exercise: Dernière occurence
En modifiant le code de l'exercice précédent, vous pouvez écrire une fonction search(lettre,txt) qui parcours la chaîne txt et qui renvoie un entier correspondant à l'indice de la dernière occurrence du caractère lettre dans txt. Si la lettre n'est pas trouvée, la fonction doit renvoyer -1.
Aide 1

Niveau 2

Fonction renverseSTR
Coding Exercise: Retournement
Ecrire une fonction renverseSTR(txt) -> str qui prend une chaine txt en paramètre, et qui renvoie la chaine txt écrite en partant de la fin :
Ex: renverseSTR("NSI") va renvoyer "ISN"
renverseSTR("loi") va renvoyer "iol"

Palindrome

Coding Exercise: Palindrome
Un palindrome est un mot qui s'écrit de la même façon à l'endroit et à l'envers. Par exemple le mot

ressasser

est un palindrome: la première et la dernière lettres sont les mêmes (r), la deuxième et l'avant dernière également (e), etc.

Ecrivez une fonction estPalindrome(S) qui prend une chaîne txt comme entrée et renvoie True si la chaîne est un palindrome etFalse autrement.

Le correcteur va générer une fonction reverseSTR similaire à celle de l'exercice précédent. Il est recommandé de l'utiliser dans cet exercice.

Niveau 3

in

Nous allons maintenant chercher non plus un caractère unique, mais une sous chaîne dans la chaine. Tout d'abord, voyons la fonction pythn qui sait déjà faire cela :

Example: sous-chaine in chaine
Savoir si une chaine s est une sous chaine d'une autre chaine txt

Mais nous voulons coder une fonction qui fasse cela. Vous aurez besoin d'étudier cet exemple :

Example: sous chaine glissée
Un autre parcours d'une chaine, ou l'on extrait une partie de la chaîne

Si vous avez bien compris les 2 exemples ci-dessus, vous pouvez maintenant réussir cet exercice :

Coding Exercise: coder in
Sans utiliser in tel que montré dans l'exemple précédent, écrire une fonction estDans(s : str,txt:str) -> bool qui renvoie True si la chaine s apparait dans la chaine txt, et False sinon. On se limitera au cas ou chechée, s, est une chaine de 2 caractères seulement.

replace et concaténation

La méthode des chaînes replace() en python permet de remplacer une sous chaine par une autre. Etudiez cet exemple :

Example: sous chaine glissée
Remplacement dans une chaine

Par ailleurs, rappelons le principe de la concaténation et au passage de la réplication :

Example: concaténation et réplication
Concaténer et réplique une chaine

Coding Exercise: remplacer
Sans utiliser replace tel que montré dans l'exemple ci-dessus, écrire une fonction remplacers(s1 : str,s2 : str, txt : str) -> str qui renvoie la chaine txt après remplacement de la première occurence de la chaine s1 par la chaine s2. Si la chaine s1 n'est pas trouvée, la fonction renvoie la chaine de départ.
Attention cet exercice est difficile. Inspirez vous de l'exercice précédent (in) et regardez les sorties attendues, comparez avec ce que vous obtenez. Avec patience vous finirez par y arriver !

P5.1 La boite à outils

  • Le tryptique CAC

  • La complexité

  • Construction de listes par ajout successifs

  • TP moyenne glissée

Premiers algorithmes

Utiliser un compteur, un accumulateur, ou un curseur

Dans de nombreux cas, on doit :

  • compter le nombre d'occurence d'une condition, dans ce cas, on utilisera un compteur
  • sommer (ou faire un produit) dans une boucle, dans ce cas, on utilisera un accumulateur
  • mémoriser la position d'un élément particulier, dans ce cas, on utilisera un curseur

Un compteur en action

Les compteur sont des variables qu'on incrémente quand on trouve un éléments correspondant à un critère. Parfois il n'y a pas vraiment de critère, on compte simplement tout les éléments ou toutes les occurrences, mais la notion de comptage est fréquente en algorithmique. Nous avons déjà vu des utilisations de compteurs.

Multiples de 3

Ecrire une fonction qui prend en argument une liste de nombres et renvoi le nombre de multiples de 3 dans cette liste

Coding Exercise: Compte les multiples de 3
Ecrire la fonction compterMult3(lst). Une liste lst sera générée pour tester votre code.

L'algorithme en pseudo-code

Le pseudo-code est indépendant du langage, c'est une description des opérations a faire pour accomplir une tâche. Il est important de bien distinguer algorithme et code. Lorsque vous écrivez un pseudo-code vous vous libérez des questions de syntaxe pour vous concentrer uniquement sur l'algorithme.

pseudo code de l'algorithme de recherche des multiples de 3 dans une liste :

fonction compterMult3(lst) :
     n ← 0
     pour element dans lst :
          si element%3 =  0 :
                 n ← n+1
          fin de si
     fin de pour
     renvoyer n

Notion de complexité

L'algorithme contient une boucle sur les éléments de la liste lst.

  • Avant la boucle on a 1 affection
  • La boucle est exécutée N fois (N=longueur de la liste)
  • Dans la boucle il y a 1 opération (%), un test, une addition et une affectation. Au total 4 opération élémentaires
  • Après la boucle il n'y a rien

On a donc au total, 4N + 1 opérations élémentaires dans ce code. 4N+1 est une fonction linéaire, on dit qu'on a une complexité linéaire et on note C=O(N)

Example
Vérifions la complexité de compterMult3()

Vous observez que lorsque le nombre N d'éléments de la liste est multiplié par 10, le temps de calcul est multiplié aussi par un facteur du même ordre de grandeur. Nous observons bien ici une complexité linéaire.

Un accumulateur en action

Pour sommer ou multiplier (ou soustraire ou diviser) dans une boucle, on utilise une variable accumulateur. Nous avons déjà vu des utilisations d'accumulateurs.

Calcul de la moyenne
Coding Exercise: Calcul de moyenne
Ecrire la fonction somme(lst). Une liste lst sera générée pour exécuter votre code.

Ici il n'est pas question de compter, mais de faire la somme. Nous avons déjà vu cet algorithme plusieurs fois.

pseudo code de l'algorithme de la moyenne :

fonction moyenne(lst) :
     somme ← 0
     pour element dans lst :
          somme ← somme + element
     fin de pour
     renvoyer somme/len(lst)

Notion de complexité

L'algorithme contient une boucle sur les éléments de la liste lst.

  • Avant la boucle on a 1 affection
  • La boucle est exécutée N fois (N=longueur de la liste)
  • Dans la boucle il y a une addition et une affectation. Au total 2 opération élémentaires
  • Après la boucle il n'y a rien

On a donc au total, 2N + 1 opérations élémentaires dans ce code. 2N+1 est une fonction linéaire, on dit ici aussi qu'on a une complexité linéaire et on note C=O(N)

Example
Vérifions la complexité de moyenne()

Vous observez là encore que lorsque le nombre N d'éléments de la liste est multiplié 10, le temps de calcul est multiplié aussi par un facteur du même ordre de grandeur. Nous observons donc encore bien ici une complexité linéaire.

Un curseur en action

Les curseurs sont des variables qui retiennent la position (l'index) d'un élément présentant une caractéristique particulière dans une liste. Un bon exemple est la recherche de la position du max des éléments d'une liste.

Indice du maximum
Coding Exercise: Indice du maximum
Ecrire la fonction idxMax(lst). Une liste lst sera générée pour exécuter votre code.

Ici il n'est pas question de compter ou de sommer, mais de mémoriser la dernière position du max parmi les éléments déjà parcourus.

pseudo code de l'algorithme de recherche de l'indice du max des éléments d'une liste :

fonction idxMax(lst) :
     idxMax ← 0
     pour i allant de 1 à len(lst)-1 :
         si lst[i] > lst[idxMax] :
               idxMax ← i
         fin de si
     fin de pour
     renvoyer n
La boucle va de 1 à len(lst) -1 si les indices vont de 0 à len(lst)-1 comme en python. on écrit i in range( 1,len(lst) )

remarque : Dans d'autres langages les indices vont de 1 à len(lst), dans ce cas la boucle ira de 2 à len(lst).

Notion de complexité

L'algorithme contient une boucle sur les éléments de la liste lst (en partant du 2ème)

  • Avant la boucle on a 1 affection
  • La boucle est exécutée N-1 fois (N=longueur de la liste)
  • Dans la boucle il y a une comparaison et une affectation. Au total 2 opération élémentaires
  • Après la boucle il n'y a rien

On a donc au total, 2N + 1 opérations élémentaires dans ce code. On a de nouveau une complexité linéaire et on note C=O(N)

Example
Vérifions la complexité de idxMax()

Vous observez là encore que lorsque le nombre N d'éléments de la liste est multiplié 10, le temps de calcul est multiplié aussi par un facteur du même ordre de grandeur. Nous observons donc encore bien ici une complexité linéaire.

Variante

Il existe une variante (qu'on retrouve généralement dans tous les algorithme utilisant un curseur) à l'algorithme que nous venons de voir.

Si, au lieu de l'indice de la valeur maxi, on cherche la valeur elle même, l'algorithme est légèrement différent.
Ecrivez le pseudo-code modifié pour satisfaire cette recherche, puis codez le ici :

Coding Exercise
Ecrire la fonction valMax(lst) qui renvoie la valeur max d'une liste
ATTENTION : vous ne pouvez pas utiliser range dans cet exercice !
pseudo code de l'algorithme de recherche du max des éléments d'une liste :

fonction valMax(lst) :
     valMax ← lst[0]
     pour i dans lst[1:] :
         si i > valMax :
               valMax ← i
         fin de si
     fin de pour
     renvoyer n

Exercices

sommes et moyenne des valeurs paires

Ecrire l'algorithme d'une fonction sommePaires(lst) qui renvoie la somme des valeurs paires d'une liste.

Multiple Choice Exercise
Dans sommesPaires vous aurez besoin d'un compteur ?
Correct!
Multiple Choice Exercise
Dans sommesPaires vous aurez besoin d'un curseur?
Correct!
Multiple Choice Exercise
Dans sommesPaires vous aurez besoin d'un accumulateur ?
Correct!

Ecrire un second algorithme pour moyPaires qui renvoie la moyenne des valeurs paires d'une liste.

Multiple Choice Exercise
Dans moyPaires vous aurez besoin d'un compteur ?
Correct!
Multiple Choice Exercise
Dans moyPaires vous aurez besoin d'un curseur?
Correct!
Multiple Choice Exercise
Dans moyPaires vous aurez besoin d'un accumulateur ?
Correct!

moyenne pondérée

N'oubliez pas que vous pouvez visualiser l'exécution de votre code pour vous aider à le mettre au point.

Coding Exercise: moyenne coefficientée
Ecrire une fonction moyPondee(notes , coefs) qui renvoie la moyenne coefficientée.
Short Answer Exercise
Combien y'a-t-il d'opération élémentaires avant la boucle ?
Correct!
Short Answer Exercise
Combien y'a-t-il d'opération élémentaires dans la boucle (en fonction du nombre N de notes) ?
Correct!
Short Answer Exercise
Combien y'a-t-il d'opération élémentaires après la boucle (seulement dans la fonction) ?
Correct!
Short Answer Exercise
Combien y'a-t-il d'opération élémentaires en tout (en fonction du nombre N de notes) ?
Correct!
Short Answer Exercise
La complexité est elle linéaire ?
Correct!

un curseur délicat

Nous avons déjà traité la question de la recherche d'un caractère dans un texte. Nous allons ici traiter un problème assez similaire mais un peu plus délicat : chercher une chaine dans une autre. Pour plus de clarté, nous appelerons mot la chaine recherchée, et texte la chaine dans laquelle on effectue la recherche.

Commencez par regarder la vidéo ci-dessous pour comprendre le problème.

Ecrivons le pseudo code :

fonction cherchePattern(mot,texte) :
     pos -> -1
     idx -> 0
     tant que idx < len(texte)-len(mot) and pos = -1
          if texte[idx:idx+len(mot)] == mot : pos = idx
          idx = idx + 1
     fin de tant que
     renvoyer pos

Coding Exercise: reverse avec pop

Construction d'une liste par ajout successifs

retourner une liste par ajout successifs

On veut retourner une liste (c'est à dire ranger ses éléments dans l'ordre inverse) et on va procéder par ajouter successifs (il existe d'autres façons de le faire).
L'algorithme est assez simple :

fonction retourner(lst) :
    lstReverse = [ ]
    tant que lst non vide :
        retirer le dernier elem de lst et l'ajouter à la fin de  lstReverse
    fin de pour
    renvoyer lstReverse
Coder ceci en python ne pose pas de grosse difficulté, mais il faut se souvenir de la méthode pop et de son usage....
Voici un code qui va te servir d'exemple pour l'exercice.

Rappel :
lst = [1,2,3]
a = lst.pop()
-> a=3 et maintenant lst=[1,2]
lst.pop() retire le dernier élément de la liste lst et renvoie sa valeur.
Coding Exercise: reverse avec pop

Au lieu de append, on pourrait aussi utiliser une concaténation de liste : lstR = lstR + [val] donnera le même résultat, essaye les deux façons.
(attention : en réalité ces deux façon de procéder ne sont pas équivalentes. Elle donnent le même résultat et pour cette année nous n'entreront pas dans les détails sr la différence de traitement entre les deux)

On pourrait même ne rien ajouter et ne rien concaténer :

def reversePOP(lst: list ) -> list :
    lstR=[0] * len(lst) # initialise une liste avec len(lst) 0
    idx=0
    while len(lst) > 0:
        e=lst.pop()
        lstR[idx]=e
        idx+=1
    return lstR
Et là encore, le résultat est le même mais les opérations réalisées ne sont pas les même en réalités. Et ici aussi nous n'entreront pas cette année dans les détails.

Toutefois nous aurions put écrire aussi bien cet algorithme :

fonction retourner(lst) :
    lstReverse = [ ]
    tant que lst non vide :
        retirer le premier elem de lst et l'ajouter au début de  lstReverse
    fin de pour
    renvoyer lstReverse
Tu pourra coder ce second algorithme en utilisant lst.pop(0) qui retire l'élément d'indice 0 et lstR.insert(0,val) qui insère val en tête de liste.

On pourrait aussi utiliser une concaténation de liste : lstR = [val] + lstR donnera le même résultat, essaye les deux façons, et surtout remarque bien :

ajouter en tête : lst.insert(0,val) ou lst=[val] + lst
ajouter en queue : lst.append(val) ou lst=lst+[val]
retirer en tête : val = lst.pop(0)
retirer en queue :val = lst.pop()

Rappel :
lst = [1,2,3]
lst.insert(0,7)
-> Maintenant lst vaut [7,1,2,3]
Coding Exercise: reverse avec insert

Ou avec l'autre façon, sans rien changer à l'algorithme, mais en remplaçant insert par une concaténation de liste :

Rappel :
lst = [1,2,3]
lst [7]+lst
-> Maintenant lst vaut [7,1,2,3]
Coding Exercise: reverse sans pop et sans insert

Complexité

Peut tu estimer la complexité des codes de retournement ? Sont ils tous équivalent ?

Trier les éléments

Vous aller programmer ici une fonction tri(lst) qui va trier une liste. L'algorithme utilisé, que nous reverrons plus tard dans une autre forme, est le suivant :

fonction triInsertion(lst) :
    listTriee=[]
    Tant que longueur(lst) > 0 :
        rechercher l'indice du min dans lst
        retirer cet élément (avec pop) et l'ajouter (en queue) dans listeTrie
    fin de tant que
    renvoyer listeTriee
(la fonction idxMin(list) est disponible dans cet exercice)
Coding Exercise

Dans ce code, que vous venez de faire, on a pas vraiment de curseurs (il y en a cependant un, caché dans la fnction idxMin que vous avez utilisé), d'accumulateur, ou de compteur. En effet ici on ne compte rien, on ne somme rien, et on ne localise rien.

L'ajout successif d'élément dans une liste est un autre outil indispensable que vous serez souvent amenés à utiliser.

Estimons la complexité de cet algorithme expérimentalement avec time().

Example

En raison de limitations sur ce site, il n'est pas pssible de travailler sur des listes très grandes. Néanmoins, ici, on a pris une séries de valeurs de N allant de 10 à 2560. A chaque fois on multiplie N par 2. Le temps de calcul évolue d'abord linéairement pour les petites valeurs de N mais rapidement on voit que quand N est multiplié par 2, le temps est multiplié par 4 (2² !)

La complexité semble donc plutot propotionelle à N² dans cet exemple.

Combien de fois est exécutée la boucle while ? Combien d'opération dans cette boucle while ?

La réponse est que la boucle while est exécutée N fois, mais dans la boucle, on appelle idxMin. idxMin a une complexité en O(N), mais comme la liste lst est raccourcie au fur et a mesure, c'est un peu compliqué....

Au premier tour, idxMin cherche dans une liste de longueur N

A second tour dans une liste de longueur N-1

Au troisième tour, dans une liste de longueur N-1

etc... jusqu'au dernier tour, ou il ne reste qu'un élément.

si le temps de idxMin est N, alors le temps de tout les appels est :

1 + 2 + ... + N = N(N+1)/2 = N² /2 + N/2

pour de grandes valeurs de N, N² >> N, la complexité sera proportionnelle à N². On parle ici de complexité quadratique.

S1 - Les fonctions

Définir une Fonction


La fonction valeur absolue

Nous allons commencer avec un exemple. Vous rappelez-vous de la fonction abs ? Elle prend seulement un argument (un nombre x), et retourne sa valeur absolue (qui devient x quand x ≥ 0 et -x quand x < 0). La façon de définir cette fonction dans Python est :

 
Example

Nous pourrions coder la même fonction différemment, sans que cela ne fasse aucune différence dans la façon de l'utiliser.

Dans cette seconde version nous introduisons 2 fois l'instruction return. Ne perdez pas de vue que, dès lors qu'une instruction return est exécutée, la fonction s'arrête (et on reprend le programme appelant là ou on l'avait arrêté).

Example

Notez que dans cette version nous n'initialisons pas la variable valeur absolue, c'est inutile, on n'utilise aucune variable, on renvoie simplement un résultat.

Exercices

Exercice 1 : Pythagore
Coding Exercise: Pythagore
Ci dessous, donne ici une fonction qui teste si a^2 +b^2 == c^2 et qui affiche si le triangle est rectangle. Cette fonction ne renvoie rien (None).

Modifiez cette procédure pour la transformer en une fonction qui renvoie True si l'égalité est vraie et False sinon.

Vous devez modifier :
  • Le corps de la fonction pour renvoyer True ou False
  • La docstring et la ligne de la définition de la fonction
  • les appels pour que le programme principal affiche le résultat de la fonction.

Exercice 2 : multiple de 3

Coding Exercise: Multiples de 3
Ci dessous une donne une fonction qui affiche les multiple de 3 jusqu'à 100.

Modifiez la fonction mult3 pour qu'elle affiche les multiples de 3 jusqu'à un entier MAX qui sera passé en paramètre.

Vous devez :
  • Modifier la définition de la fonction, pour passer un paramètre suplémentaire n_max
  • modifier le corps de la fonction pour n\'afficher les multiples de 3 que jusqu'à n_max
  • modifier la docstring
Le correcteur va générer un entier n_max pour exécuter et tester la fonction.

Exercice 3 : puissance
Coding Exercise: Puissance
Ecrire une fonction qui prend 2 arguments a et k et qui renvoie la valeur de a^k .

Vous devez :
  • complétez la définition de la fonction, en ajoutant les paramètres et le type de la sortie
  • écrire le corps de la fonction
  • écrire la docstring
Vous ,
Exercice 4 : plus grande valeur
Coding Exercise: Plus grande valeur
Ecrire une fonction qui renvoie la plus grande de 2 valeurs entières passées en paramètres.

Vous placerez des appels avec ces valeurs comme exemple pour tester :
plusGrandeValeur(4, 9) renverra 9
plusGrandeValeur(2, 1) renverra 2
Exercice 5 : Vitesse moyenne
Coding Exercise: Vitesse Moyenne
Ecrire une fonction qui calcule la vitesse moyenne d'une voiture, connaissant son temps de parcours (en heures) et la distance parcourue (en km)

Ex: vitesseMoyenne(4, 300) renverra 75
Le programme principal affichera 75 km/h

Bonnes pratiques de programmation

Préciser le typage de chacun des paramètres

Le langage Python est plus aisé pour démarrer la programmation pour la concision des codes écrits et pour la gestion automatique du typage par l'interpréteur. Cependant, le but est que vous puissiez à terme être capable de faire basculer vos compétences acquises en NSI sur Python vers d'autres langages de programmation.

Comme la plupart des langages de programmation nécessitent la spécification du typage des variables, on vous demandera d'écrire en Python, une fonction en précisant le type de chaque entrée et sortie en suivant le même formalisme ci-dessous :

def nomFonction(argument: type) -> typeRetour:
		blocs des instructions
		return résultat
	
Example: Typer les arguments et les résultats
Exemple : ici on précise dans la définition que le paramètre x est float et que la fonction renvoie aussi un float.

Nommage

La convention PEP8 donne l'habitude de nommer les fonctions (comme les variables) avec des lettres minuscules et des tirets bas (celui du "8") _.


Exemples : lire_fichier, resoudre_equation, creer_grille_vide etc...

Comme pour les noms de variables, il est absolument recommandé de ne pas utiliser de caractères accentués dans les noms des fonctions.


On préfère toutefois parfois (ou souvent suivant les personnes) la convention dite camelCase qui consiste a écrire en minuscules, mais si le nom est constitué de plusieurs mots, on met une majuscules à tous les mots sauf le premier. Exemples : lireFichier, resoudreEquation, creerGrilleVide etc...

Pour clarifier la fonction, il est conseillé d'utiliser un verbe dans son nom (obtenir, donner, get, set, ...).

Documenter ses fonctions

Il est important de documenter vos fonctions, c'est-à-dire de décrire en quelques phrases le rôle de la fonction, de donner des informations sur la fonction, le lien entre les entrées et la sortie.

Pour cela, juste en dessous de la première ligne définissant la fonction, il suffit de mettre ses informations de préférence entre """ """ ou entre''' ''' et ''' ; c'est ce que l'on appelle en franglais le docstring de la fonction).
Dans la docstring vous indiquerez ce que sont les paramètres et ce que renvoi la fonction, sous cette forme :

Example
Documenter une fonction, accéder à la documentation

L'intérêt de l'auto-documentation d'une fonction par un texte est double :

  • Pour vous : le faire vous oblige à réfléchir au contenu de votre fonction avant de la programmer ; c'est un gain d'efficacité,
  • Pour les utilisateurs de votre code (ou pour vous longtemps après avoir programmé la fonction) : Quand on saisit dans la console, après l'exécution de la fonction, l'instruction help(nom de la fonction), Python affiche le docstring de la fonction ce qui nous permet d'avoir des informations sur la fonction en cas d'oubli.

A faire seulement après avoir étudié les listes : fonctions traitant des listes

Utiliser un compteur ou un accumulateur

Dans de nombreux cas, on doit :

  • compter le nombre d'occurrences d'une condition
  • sommer une quantité
  • faire un produit de façon répétée

Dans ces cas, on utilisera un compteur ou un accumulateur.

Multiples de 3

Un compteur en action

Ecrire une fonction qui prend en argument une liste de nombres entiers et renvoie le nombre de multiples de 3 dans cette liste

Coding Exercise: Compte les multiples de 3
Ecrire la fonction compterMult3(lst). Une liste lst sera générée pour tester votre code.
Calcul de la moyenne
Coding Exercise: Calcul de moyenne
Ecrire la fonction moyenne(lst). Une liste lst sera générée pour exécuter votre code.
Détermination de la médiane

Déterminer la médiane d'une série statistique

Rappel de l'algorithme de la médiane

Soit lst=[x1, x1, ...xN] une série de nombres (la série contient N éléments) ordonnée dans l'ordre croissant.

  • Si N est pair la médiane est la moyenne des valeurs de rang N/2 et N/2 + 1
  • Si N est impair, la médiane est la valeur de rang (N+1)/2
Coding Exercise: Déterminer la médiane
Ecrire une fonction qui prend en argument une liste de nombre triée en ordre croissant, et renvoie la médiane de la liste. Une liste lst sera générée pour exécuter votre code.