Exo Tableaux

Identification

Infoforall

24 - Exos Tableaux 1


Attention, le soin est noté et les codes markdown identiques seront sanctionnés à moins de noter clairement que vous avez travaillé avec un autre élève de la classe.

1 - Lecture

Un petit rappel du cours à vraiment comprendre et maîtriser avant de commencer.
Rappel

Pour parvenir à accéder aux valeurs contenues dans un tableau, il existe deux méthodes.

Possibilité n°1 : utilisation d'un FOR sur les index du tableau

1 2 3 4
notes = [15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 18, 4] for index in range( len(notes) ): print(notes[index], end="-")

La variable de boucle index va alors prendre successivement les valeurs 0, 1, 2...

On obtient alors ceci

15-18-8-10-12-15-20-5-12-17-12-10-18-4-

Possibilité n°2 : utilisation d'un FOR sur la variable du tableau elle-même : accès directe aux valeurs en lecture seule.

1 2 3 4
notes = [15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 18, 4] for element in notes : print(element, end="-")

La variable de boucle element va alors prendre successivement les valeurs 15, 18, 8...

On obtient alors ceci

15-18-8-10-12-15-20-5-12-17-12-10-18-4-

01° Que va contenir la variable a lors des tours de boucle successifs ? S'il ne s'agit pas de la valeur contenue dans la case, que faudrait-il noter pour obtenir ce contenu ?

1 2 3 4
notes = [15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 18, 4] for a in notes : print(a, end="-")

02° Que va contenir la variable a lors des tours de boucle successifs ? S'il ne s'agit pas de la valeur contenue dans la case, que faudrait-il noter pour obtenir ce contenu ?

1 2 3 4
notes = [15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 18, 4] for a in range( len(notes) ): print(a,end="-")

2 - Modification

Un petit rappel du cours à vraiment comprendre et maîtriser avant de commencer.
Rappel

Pour modifier les cases d'un tableau, nous n'avons pas le choix : il faut passer par la méthode de l'index : il faut utiliser l'adresse du tableau (contenue dans la variable du tableau) et aller modifier la valeur placée sur un index précis.

Exemple valide : modification d'un tableau

Voici une fonction qui modifie tout le contenu du tableau qu'on reçoit en paramètre : on y place le string "Bonjour" dans toutes les cases.

1 2 3 4
def remplacer(tableau): """Remplace toutes les cases de tableau par "Bonjour"""" for index in range( len(tableau) ): tableau[index] = "Bonjour"

Remarquez bien l'absence de return : on modifie le tableau, on n'en crée pas un nouveau qu'on renvoie.

Pour l'utiliser :

>>> base = [10, 20, 30] >>> remplacer(base) >>> base ['bonjour', 'bonjour', 'bonjour']

Exemple valide 2 : Renvoi d'un tableau basé sur le premier.

On crée et renvoie un tableau qui a le même nombre de cases mais qui ne contient que "Bonjour".

1 2 3 4 5 6
def creer(tableau_initial): """Crée un nouveau tableau basé sur le tableau initial mais ne contenant que "Bonjour"""" reponse = [None for case in tableau_initial] for index in range( len( reponse) ): reponse[index] = "Bonjour" return reponse

On notera cette fois la présence d'un return : il faut donc placer cette réponse dans une variable qui contiendra alors un nouveau tableau.

Utilisation :

>>> base = [10, 20, 30] >>> resultat = creer(base) >>> base [10, 20, 30] >>> resultat ['Bonjour', 'Bonjour', 'Bonjour']

Exemple valide 3 : Renvoi d'un tableau basé sur le premier.

Comme au dessus : on crée et renvoie un tableau qui a le même nombre de cases mais qui ne contient que "Bonjour". On utilise juste directement la création par compréhension.

1 2 3 4
def creer2(tableau_initial): """Crée un nouveau tableau basé sur le tableau initial mais ne contenant que "Bonjour"""" reponse = ["Bonjour" for case in tableau_initial] return reponse

Toujours un return : on crée bien un nouveau tableau.

Utilisation :

>>> base = [10, 20, 30] >>> resultat = creer2(base) >>> base [10, 20, 30] >>> resultat ['Bonjour', 'Bonjour', 'Bonjour']

03° On veut créer une fonction qui modifie par effet de bord un tableau en rajoutant 10 à toutes les valeurs dont l'index est strictement supérieur à 3. On ne veut donc pas renvoyer le tableau ou une copie du tableau. On veut le modifier sur place.

Voici quelques propositions fournies par des élèves.

Pour chacune d'elle, dire si c'est bon (en le justifiant un peu), si c'est faux (en expliquant ce qui est faux).

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
# Proposition 1 def rajouter(tableau): for index in range( len(tableau) ): if index > 3 : tableau[index] = tableau[index] + 10 # Proposition 2 def rajouter(tableau): for index in range( len(tableau) ): if index > 3 : tableau[index] = tableau[index] + 10 return tableau # Proposition 3 def rajouter(tableau): for valeur in tableau : if index > 3 : valeur = valeur + 10 # Proposition 4 def rajouter(tableau): for valeur in tableau : if index > 3 : valeur = valeur + 10 return tableau

3 - Fonction et tableau

04° Créer une fonction qui attend un tableau de notes en paramètres. Elle renvoie True si toutes les notes sont valides. Sinon, False

05° Créer une fonction qui attend un tableau de notes en paramètres. Elle renvoie une copie du tableau en remplaçant les notes par 0 si moins que 10 et 20 si 10 ou +. On ne modifie pas le tableau initial : on en crée un nouveau.

06° Un élève propose cette version erronée d'une fonction qui doit renvoyer un tableau d'entiers crée à partir d'un tableau de strings. "10" doit devenir 10... La présence d'un "A" implique une note de 0.

Son test lui montre que son programme n'agit que sur le premier élément.

>>> ds ['20', '15', '5', 'A', '2', '12', '18'] >>> notes = str_en_int(ds) >>> notes [20, '15', '5', 'A', '2', '12', '18']

Seule la première note est bien un integer...

Il y a une erreur d'inattention qui provoque ce fonctionnement douteux. Trouver l'erreur. Modifier le programme.

1 2 3 4 5 6 7 8 9 10
ds = ["20", "15", "5", "A", "2", "12", "18"] def str_en_int(initial): final = [valeur for valeur in initial] for index in range( len(final) ): if final[index] == 'A' : final[index] = 0 else : final[index] = int(final[index]) return final

07° Un autre élève propose cette version correcte. Expliquer le plus clairement possible comment cela fonctionne.

1 2 3 4 5 6 7 8 9 10
ds = ["20", "15", "5", "A", "2", "12", "18"] def convertir(contenu): if contenu == 'A' : return 0 return int(contenu) def str_en_int(initial): final = [convertir(valeur) for valeur in initial] return final
>>> ds ['20', '15', '5', 'A', '2', '12', '18'] >>> notes = str_en_int(ds) >>> notes [20, 15, 5, 0, 2, 12, 18]

08° Voici deux versions d'une fonction qui renvoie un tableau dont le contenu est, pour chaque case, le double du tableau d'entrée.

1 2 3 4 5 6 7 8 9
def doubler(entree): reponse = [valeur*2 for valeur in entree] return reponse def doubler_bis(entree): reponse = [None for valeur in entree] for index in range( len(reponse) ): reponse[index] = entree[index] * 2 return reponse

Réaliser la documentation à rajouter sur ces fonctions :

  • Petite phrase explicative
  • Description du paramètre (dont le type)
  • Description de la réponse éventuelle (dont le type)
  • Un exemple qui pourra être utilisé par le module doctest si on l'active, et qui ne sert que de documentation sinon.

09° Voici une fonction courte sur laquelle les spécifications sont indiquées directement sur la première ligne, version ultracourte de documentation.

Quelle est la forme de documentation des spécifications en typing correcte ? Justifiez les cas jugés faux.

1 2 3 4 5 6 7 8 9 10 11
def doubler(entree:int) -> int : reponse = [valeur*2 for valeur in entree] return reponse def doubler(entree:list) -> list : reponse = [valeur*2 for valeur in entree] return reponse def doubler(entree:list) -> None : reponse = [valeur*2 for valeur in entree] return reponse

10° Voici une fonction qui crée un nouveau tableau à partir du tableau d'entrée. Il place à l'index 1 la somme de l'index 0 et 1 de l'ancien. Il place à l'index 2 la somme de l'index 0, 1 et 2 de l'ancien...

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
def bizarre(entree): """Fonction qui crée et renvoie un tableau créé à partir de entree :: param entree(list) :: un tableau d'entiers :: return (list) :: un tableau crée à partir de entree :: exemple :: >>> donnees = [1, 2, 3, 4] >>> nouveau = bizarre(donnees) >>> nouveau [1, 3, 6, 10] """ reponse = [int(valeur) for valeur in entree] for index in range( 1, len(reponse) ): reponse[index] = reponse[index] + reponse[index - 1] return reponse if __name__ == '__main__' : import doctest doctest.testmod()

Rajouter

  • une assertion pour imposer la précondition : entree est un tableau (de type list en Python) et
  • une assertion pour imposer la postcondition : reponse est un tableau

Expliquer ensuite ce qui provoque cette erreur si on envoie pas un tableau d'entiers :

  • A : la fonction testmod du module doctest
  • B : vos assertions
  • C : une des instructions du code de la fonction
  • D : la documentation présente dans la fonction

En conclusion :

  1. Pour lire le contenu d'un tableau depuis une fonction : deux méthodes possibles
    • L'accès via l'index
    • 1 2 3 4 5 6
      def afficher(tableau): for index in range( len(tableau) ): print(tableau[index]) notes = [15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 18, 4] afficher(notes)
    • L'accès en lisant directement le contenu des 'cases'
    • 1 2 3 4 5 6
      def afficher(tableau): for element in tableau : print(element) notes = [15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 18, 4] afficher(notes)
  2. Pour modifier un tableau depuis une fonction : une seule méthode utilisable : l'accès via l'index.
  3. 1 2 3 4 5 6
    def modifier(tableau): for index in range( len(tableau) ): tableau[index] = tableau[index] ** 2 notes = [15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 18, 4] modifier(notes)
  4. Pour renvoyer un nouveau tableau basé sur un tableau-paramètre depuis une fonction : une seule méthode utilisable :
    • Créer une copie du tableau initial
    • Modifier la copie en utilisant les index
    • Renvoyer la copie (et la stocker dans une variable !)
    1 2 3 4 5 6 7 8
    def copier_et_modifier_la_copie(tableau): copie = [valeur for valeur in tableau] for index in range( len(copie) ): copie[index] = copie[index] * 2 return copie notes = [15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 18, 4] nouvelles_notes = copier_et_modifier_la_copie(notes)

Activité publiée le 15 09 2020
Dernière modification : 15 09 2020
Auteur : ows. h.