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

Exercice de code : 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

Exercice de code : 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

Exercice de code : 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...

Exercice de code : 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.

Exercice de code : 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.
Exercice de code : 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

Exercice de code : 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

Exercice de code : 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

Exercice de code : 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

Exercice de code : 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 :

Exemple : Objets géométriques

 

Application :

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

Exercice de code : 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 :

Exemple : à 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 :

Exercice de code : 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