Tant que ce n'est pas bien maîtrisé c'est ...

La Guerre des Fonctions

  • 1) Autes fonctions particulières à corriger
  • 2) Exercices de Simplification du code des fonctions
  • 3) Quelques Exercices

L'objet de ce cours est de vous faire progresser dans l'ameilloration de votre capacité de comprendre le fontionnement des algorithmes, par la pratique des tâches consistant à DEBUGER et à SIMPLIFIER des fonctions SANS modifier leur sens.

Les fonctions ici presentes, ne modifient pas leurs ENTRÉES, elles sont donc essentiellement déterminées par la valeur de SORTIE (après le return).

Encore une fois les variables locales des fonctions n'ont pas d'importance tant quelles ne ne modifient pas la valeur de retour.

Des exemples sont fournis pour chaque fonction, mais ne ils sont pas suffisant pour garantir que la fonction n'a pas du tout été modifiée.

Le but de l'exercice est de vous évaluer en fonction :

  • du fait que vous n'ayez pas dénaturé le retour de la fonction
  • de votre capacité à ecrire un code simple et clair

Dans le cas présent, on pourra approximer "simplification" par réduction du nombre de ligne.
Vous pouvez également améliorer la fonction en réduisant le nombre d'itération nécessaire si il s'agit d'une fonction utilisant des boucles.

Dans tous les cas veuillez ajouter des commentaires, voire des docstrings.

        Attention pour les exercices suivants !!!

NE SURTOUT PAS MODIFIER LES DEUX LIGNES DE COMMENTAIRES DIRECTEMENT DANS EN-TÊTE DES FONCTIONS.

TOUTE MODIFICATION, voire même d'un CHARACTERE ESPACE entrainera une penalité

Ceux-ci servent aussi à documenter la fonction

Une indication est donnée (plus ou moins précise) du nombre de ligne que l'on peut atteindre.

Sauf indication contraire, vous pouvez utiliser toutes les librairies de python, vus en cours (math, matplotlib).

Vous pouvez également utilisez les fonctions système vus egualement en cours.

1) Definir la fonction cube symmetrique par rapport a y


In [1]:
def cube_positif( x ):
    if abs( x*x*x >= 0.0):
        return x*x*x
    print("Erreur")
    return

In [2]:
cube_positif(-4)


Erreur

Maintenant on peux se servir de %inline matplotlib import matplotlib.pyplot as plt pour obennir le graphe de la fonction cube symmetrique par rapport à l'axe y

  • quelles sont les modifications de le la fonction cube_positif(x) ?
  • de combien de return a t'on besoin ?

In [3]:
%matplotlib inline 
import matplotlib.pyplot as plt
#On commence sans fonction,

XX=[]
YY=[]
X=range(10,-10,-1)
for x in X:
    XX.append(x)
    YY.append(x*x*x)
    
plt.plot(XX,YY)


Out[3]:
[<matplotlib.lines.Line2D at 0xad68010c>]

In [4]:
def cube_positif( x ):
    if x*x*x >= 0.0:
        return x*x*x
    elif x*x*x <= 0.0:
        return -1*x*x*x
#On peut simplifier cette fonction

#On va s'en servir de la façon suivante:
XX=[]
YY=[]

X=range(10,-10,-1)
for x in X:
    XX.append(x)
    YY.append(cube_positif( x ))

plt.plot(XX,YY)
plt.show()


2) Correction de fonctions en vrac (les fonction suivantes doivent être corrigées)

2.1) Test des entiers et des premiers


In [ ]:
def est_entier(x):
    return x == int(x)

def est_premier(n):
    if n < 2:
        return False
    for it in range(2,int(n**0.5)+1):
        if n % it == 0:
            return False
    return True

In [ ]:
n=float(input())
print("est entier ? : {}".format(est_entier(n)))
print("est premier ? : {}".format(est_premier(n)))
#Que se passe t'il si l'on ne force pas n a être un nombre  ?
#Que se passe t'il si on a un nombre a virgule (float) ?
#Est ce que ce nombre doit être nécessairement un int ou est ce que cela peut être autre chose ?

2.2) Factorielle : Exercice 1


In [ ]:
## Référence - à priori ne la modifiez pas, s'il vous plaît

def factorielle( int( n ) ):
    res = 1
    for it in range(1,n+1):
        res = res*it
return res
#Aide:
#Cette partie du code contiens deux erreurs
#Un problème de passage de variable
#Un problème lié a l'appartenance à un bloc

In [ ]:
## DM - exercice n°1
## Modifiez le code ci-dessous, et ne modifiez pas ces commentaires
def factorielle( int( n ) ):
    res = 1
    for it in range(1,n+1):
        res = res*it
return res

In [ ]:
print( factorielle( 10 ) )
#devrait donner 3628800

3) Exercices de simplification

3.1) Exercice 2 : simplification de la fonction est_pair()

Simplifier la fonction suivante, qui renvoit True si un nombre est pair, False sinon.

Indication : On peut en faire une version très très courte.


In [ ]:
## Référence - à priori ne la modifiez pas, s'il vous plaît
def est_pair(n):
    if n % 2 == 0:
        return True
    else:
        return False

In [ ]:
## DM - exercice n°2
## Modifiez le code ci-dessous, et ne modifiez pas ces commentaires
def est_pair(n):
    if n % 2 == 0:
        return True
    else:
        return False

La cellule suivante doit afficher 2 => True, 3 => False


In [ ]:
print( "2 => ", est_pair(2) )
print( "3 => ", est_pair(3) )

3.2) Exercice 2 : fonction a un seul diviseur

Simplifier la fonction suivante, qui renvoit True si un nombre possède 1 et un unique diviseur différent de 1 et lui-même, False sinon.

Pour le coup on ne peut pas beaucoup réduire le code de la fonction, sauf à changer l'algorithme (pour un résultat équivalent). En modifiant l'algorithme, on peut l'écrire en une ligne (en utilisant les bonnes fonctions)


In [ ]:
## Référence - à priori ne la modifiez pas, s'il vous plaît
def possede_un_seul_diviseur(n):
    nb_diviseur = 0
    for it in range(2,n):
        if n % it == 0:
            nb_diviseur = nb_diviseur + 1
    if nb_diviseur == 1:
        return True
    return False

In [ ]:
## DM - exercice n°3
## Modifiez le code ci-dessous, et ne modifiez pas ces commentaires
def possede_un_seul_diviseur(n):
    nb_diviseur = 0
    for it in range(2,n):
        if n % it == 0:
            nb_diviseur = nb_diviseur + 1
    if nb_diviseur == 1:
        return True
    return False

La cellule suivante doit afficher 4 => True, 6 => False


In [ ]:
print( "4 => ", possede_un_seul_diviseur(4) )
print( "6 => ", possede_un_seul_diviseur(6) )

3.3 Exercice 3: fonction somme partielle

On définit une fonction somme_partielle, qui prend en argument une liste de 9 éléments et renvoit une liste de trois éléments, les sommes des 3 premiers éléments, des 3 suivants et des 3 derniers.

Par exemple :

a = somme_partielle( [1,2,3,4,5,6,7,8,9] )
print( a ) ## Affiche [6, 15, 24]
b = somme_partielle( [0,1,5,0,1,7,0,1,9] )
print( b ) ## Affiche [6,8,10]

On peut écrire cette fonction en 6 lignes.


In [ ]:
## Référence - à priori ne la modifiez pas, s'il vous plaît
def somme_partielle(liste):
    if len(liste) != 9:
        return None
    
    a1 = 0
    for it in range(0, len(liste[0:3])):
        a1 = a1 + liste[it]
    a2 = 0
    for it in range(3, len(liste[3:6])):
        a2 = a2 + liste[it]
    a3 = 0
    for it in range(6, len(liste[6:9])):
        a3 = a3 + liste[it]
        
    res = []
    res.append(a1)
    res.append(a2)
    res.append(a3)
    return res

In [ ]:
## DM - exercice n°4
## Modifiez le code ci-dessous, et ne modifiez pas ces commentaires
def somme_partielle(liste):
    if len(liste) != 9:
        return None
    
    a1 = 0
    for it in range(0, len(liste[0:3])):
        a1 = a1 + liste[it]
    a2 = 0
    for it in range(3, 3 + len(liste[3:6])):
        a2 = a2 + liste[it]
    a3 = 0
    for it in range(6, 6 + len(liste[6:9])):
        a3 = a3 + liste[it]
        
    res = []
    res.append(a1)
    res.append(a2)
    res.append(a3)
    return res

La cellule suivante doit afficher [6,15,24] et [6,8,10]


In [ ]:
a = somme_partielle( [1,2,3,4,5,6,7,8,9] )
print( a ) ## Affiche [6, 15, 24]
b = somme_partielle( [0,1,5,0,1,7,0,1,9] )
print( b ) ## Affiche [6,8,10]

3.4) Exercice 4 : vérifiez que tous les éléments d'une liste soient égaux

On veut écrire une fonction qui vérifie que tous les éléments d'une liste sont bien égaux entre eux.

On peut la réduire d'à peu près de moitié.


In [ ]:
## Référence - à priori ne la modifiez pas, s'il vous plaît
def verifier_si_tous_les_elements_sont_egaux(liste):
    nb_egaux = 0
    for it in liste:
        for it2 in liste:
            if it != it2:
                return False
            else:
                nb_egaux += 1
    if nb_egaux == len(liste)**2:
        return True
    else:
        return False

In [ ]:
## DM - exercice n°5
## Modifiez le code ci-dessous, et ne modifiez pas ces commentaires
def verifier_si_tous_les_elements_sont_egaux(liste):
    nb_egaux = 0
    for it in liste:
        for it2 in liste:
            if it != it2:
                return False
            else:
                nb_egaux += 1
    if nb_egaux == len(liste)**2:
        return True
    else:
        return False

La cellule suivante doit afficher cas 1 => True, cas 2 => False


In [ ]:
print("Cas 1 =>", verifier_si_tous_les_elements_sont_egaux([1,1,1,1,1,1,1,1]))
print("Cas 2 =>", verifier_si_tous_les_elements_sont_egaux([1,1,1,1,1,1,1,2]))

3.5) Exercice 5 - fizzbuzz

On définit une foction fizzbuzz, qui prend un argument n et, pour tous les nombres de 1 à n :

  • affiche fizz si le nombre est divisible par 3
  • affiche buzz si le nombre est divisible par 5
  • affiche fizzbuzz si il est à la fois divisible par 3 et 5
  • affiche le nombre si aucun des cas ci-dessus n'est réalisé

Beaucoup de choses à simplifier dans cette fonction, par contre cela ne se traduira pas forcément par des lignes en moins. on peut quand même gagner quelques lignes.


In [ ]:
## Référence - à priori ne la modifiez pas, s'il vous plaît
def fizzbuzz(n):
    it = 1
    while it <= n:
        if (it % 3 == 0) and (it % 5 == 0):
            print("fizzbuzz")
        if (it % 3 == 0) and (it % 5 != 0):
            print("fizz")
        if (it % 3 != 0) and (it % 5 == 0):
            print("buzz")
        if (it % 3 != 0) and (it % 5 != 0):
            print(it)
        it = it + 1

In [ ]:
## DM - exercice n°6
## Modifiez le code ci-dessous, et ne modifiez pas ces commentaires
def fizzbuzz(n):
    it = 1
    while it <= n:
        if (it % 3 == 0) and (it % 5 == 0):
            print("fizzbuzz")
        if (it % 3 == 0) and (it % 5 != 0):
            print("fizz")
        if (it % 3 != 0) and (it % 5 == 0):
            print("buzz")
        if (it % 3 != 0) and (it % 5 != 0):
            print(it)
        it = it + 1

La cellule suivante doit afficher :
1
2
fizz
4
buzz
fizz
7
8
fizz
buzz
11
fizz
13
14
fizzbuzz
16
17
fizz
19
buzz


In [ ]:
fizzbuzz(20)

3.6) Exercice 7 - calcul de combinatoire

On cherche à calculer les combinatoires de n, k, à l'aide de la fonction math.factorial. La formule est la suivante :

$$\displaystyle \frac{ n! }{ k!(n-k)! }$$

On peut obtenir une version très courte de cette fonction.


In [ ]:
## Référence - à priori ne la modifiez pas, s'il vous plaît
import math
def combinatoire(n,k):
    a = math.factorial(n)
    a = a // math.factorial(k)
    a = a // math.factorial(n-k)
    return a

In [ ]:
## DM - exercice n°7
## Modifiez le code ci-dessous, et ne modifiez pas ces commentaires
import math
def combinatoire(n,k):
    a = math.factorial(n)
    a = a // math.factorial(k)
    a = a // math.factorial(n-k)
    return a

La cellule ci-dessous doit afficher C(4,2) => 6, C(6,3) => 20


In [ ]:
print( "C(4,2) =>", combinatoire(4,2) )
print( "C(6,3) =>", combinatoire(6,3) )

3.7) Exercice 8 - fonction maximum_pair

Simplifiez la fonction suivante qui renvoit le plus grand nombre pair d'une liste ne contenant que des nombres pairs positifs, ou 0 si la liste ne contient aucun nombre pair.

On peut raisonnablement l'écrire en 5 ligne (voir en une ligne avec la list-comprehension, mais elle n'est pas au programme)


In [ ]:
## Référence - à priori ne la modifiez pas, s'il vous plaît
def maximum_pair(liste):
    for it in liste:
        if it % 2 == 0:
            est_le_plus_grand = True
            for it2 in liste:
                if (it2 % 2 == 0) and it2 > it:
                    est_le_plus_grand = False
                    break
            if est_le_plus_grand == True:
                return it
    return 0

In [ ]:
## DM - exercice n°8
## Modifiez le code ci-dessous, et ne modifiez pas ces commentaires
def maximum_pair(liste):
    for it in liste:
        if it % 2 == 0:
            est_le_plus_grand = True
            for it2 in liste:
                if (it2 % 2 == 0) and it2 > it:
                    est_le_plus_grand = False
                    break
            if est_le_plus_grand == True:
                return it
    return 0

La cellule suivante doit afficher cas 1 => 12, cas 2 => 0


In [ ]:
print( "cas 1 =>", maximum_pair([1,2,4,13,12,10,8]))
print( "cas 2 =>", maximum_pair([1,21,41,13,125,109,87]))

3.8) Exercice 9 - Fonction carre magique

On code une fonction qui détermine si une liste en entrée correspond à un carré magique de taille 3, c'est à dire qu'il s'agit d'une liste de liste de même longueur, dont les sommes sur les lignes et les colonnes sont égales et tous les termes différents.

Courage : il y a des carres magiques partout dans Paris Carre Magique Porte d'Auteil et parfois ils sont bien plus compliqués


In [ ]:
## Référence - à priori ne la modifiez pas, s'il vous plaît
def carre_magique(carre_magique):
    if len(carre_magique) != 3:
        return False
    
    for it_ligne in carre_magique:
        if len(it_ligne) != 3:
            return False
        
    for it_ligne_1 in carre_magique:
        for it_ligne_2 in carre_magique:
            if id(it_ligne_1) != id(it_ligne_2):
                for it_elt1 in it_ligne_1:
                    for it_elt2 in it_ligne_2:
                        if it_elt1 == it_elt2:
                            return False
    
    somme_ligne_1 = 0
    somme_ligne_2 = 0
    somme_ligne_3 = 0
    ligne_1 = carre_magique[0]
    ligne_2 = carre_magique[1]
    ligne_3 = carre_magique[2]
    
    for it in ligne_1:
        somme_ligne_1 = somme_ligne_1 + it
    for it in ligne_2:
        somme_ligne_2 = somme_ligne_2 + it
    for it in ligne_3:
        somme_ligne_3 = somme_ligne_3 + it
        
    if (somme_ligne_1 != somme_ligne_2) or (somme_ligne_1 != somme_ligne_3) or (somme_ligne_2 != somme_ligne_3):
        return False
    
    somme_colonne_1 = 0
    somme_colonne_2 = 0
    somme_colonne_3 = 0

    for it in range(3):
        somme_colonne_1 = somme_colonne_1 + carre_magique[it][0]
    for it in range(3):
        somme_colonne_2 = somme_colonne_2 + carre_magique[it][1]
    for it in range(3):
        somme_colonne_3 = somme_colonne_3 + carre_magique[it][2]
        
    if (somme_colonne_1 != somme_colonne_2) or (somme_colonne_1 != somme_colonne_3) or (somme_colonne_2 != somme_colonne_3):
        return False
    
    return True

In [ ]:
## DM - exercice n°9
## Modifiez le code ci-dessous, et ne modifiez pas ces commentaires
def carre_magique(carre_magique):
    if len(carre_magique) != 3:
        return False
    
    for it_ligne in carre_magique:
        if len(it_ligne) != 3:
            return False
        
    for it_ligne_1 in carre_magique:
        for it_ligne_2 in carre_magique:
            if id(it_ligne_1) != id(it_ligne_2):
                for it_elt1 in it_ligne_1:
                    for it_elt2 in it_ligne_2:
                        if it_elt1 == it_elt2:
                            return False
    
    somme_ligne_1 = 0
    somme_ligne_2 = 0
    somme_ligne_3 = 0
    ligne_1 = carre_magique[0]
    ligne_2 = carre_magique[1]
    ligne_3 = carre_magique[2]
    
    for it in ligne_1:
        somme_ligne_1 = somme_ligne_1 + it
    for it in ligne_2:
        somme_ligne_2 = somme_ligne_2 + it
    for it in ligne_3:
        somme_ligne_3 = somme_ligne_3 + it
        
    if (somme_ligne_1 != somme_ligne_2) or (somme_ligne_1 != somme_ligne_3) or (somme_ligne_2 != somme_ligne_3):
        return False
    
    somme_colonne_1 = 0
    somme_colonne_2 = 0
    somme_colonne_3 = 0

    for it in range(3):
        somme_colonne_1 = somme_colonne_1 + carre_magique[it][0]
    for it in range(3):
        somme_colonne_2 = somme_colonne_2 + carre_magique[it][1]
    for it in range(3):
        somme_colonne_3 = somme_colonne_3 + carre_magique[it][2]
        
    if (somme_colonne_1 != somme_colonne_2) or (somme_colonne_1 != somme_colonne_3) or (somme_colonne_2 != somme_colonne_3):
        return False
    
    return True

La cellule suivante doit afficher True, False, False


In [ ]:
print( carre_magique([[2,9,4],
                      [7,5,3],
                      [6,1,8]]))
print( carre_magique([[2,9,4],
                      [7,5,10],
                      [6,1,8]]))
print( carre_magique([[1,1,1],
                      [1,1,1],
                      [1,1,1]]))

3.9) Utilisation avancée des graphes : Exercice 10

comment s'y prendre pour avoir un graphe en 3D de la fonction $$Z=X^3.Y^3$$

    Pour résoudre cet exercice il faut importer les librairies suivantes dans spyder
    Le code suivant vous sert de point de départ :

## Référence à completter en remplaçant les lignes qui commencent par #-
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm # Couleur
from numpy import meshgrid
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.gca(projection='3d')
#- definir X
#- definir Y
#- definir X, Y en utilisant la fonction meshgrid
#- definir Z

## Ici nous definisons le graphe 3D comme une surface 
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm,
                       linewidth=0, antialiased=False)
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()

Vu la taille que peut prendre le graphe, il n'est pas judicieux de l'envoyer avec le notebook Le fichier sera rennomé sous le nom: "Fonctions_Prenom_NOM.ipynb" et corrige si et seulement si il est lisible sur les ordinateurs de l'ISEP