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.
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)
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
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]:
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()
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 ?
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
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) )
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) )
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]
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]))
On définit une foction fizzbuzz, qui prend un argument n et, pour tous les nombres de 1 à n :
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)
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) )
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]))
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]]))
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