def Occurrences(a, L):
"""
Renvoie le nombre d'occurences (i.e. d'apparitions)
de l'élément a dans la liste L
"""
n = 0 # initialisation du compteur
for k in range(len(L)):
if a == L[k]: # test d'égalité + confusion entre k et L[k] + oubli des ":"
n = n + 1
return n # mauvaise indentation
# test avec la liste vide
Occurrences(1, [])
# test avec plusieurs occurences
Occurrences(1, [1, 2, 3, 4, 1, 2, 3, 4, 1])
# test sans occurrence
Occurrences(1, [2, 3, 4, 5])
On pourrait également utiliser un autre type de parcours de liste, qui se fait élément par élément :
def Occurrences(a, L):
"""
Renvoie le nombre d'occurences (i.e. d'apparitions)
de l'élément a dans la liste L
"""
n = 0
for elt in L:
if a == elt:
n = n + 1
return n
On va utiliser une liste par compréhension :
import random as rd
def listealeatoire(n, a, b):
"""
Renvoie une liste de n entiers aleatoires compris entre a et b.
"""
return [rd.randint(a, b) for i in range(n)]
listealeatoire(4, 1, 5)
[5, 1, 1, 2]
listealeatoire(0, 1, 10)
[]
listealeatoire(3, 2, 2)
[2, 2, 2]
On adapte un script du TP précédent pour le transformer en fonction :
def maxi(L):
"""
Renvoie le maximum des elements d’une liste de nombres L.
"""
M = L[0]
for k in range(len(L)):
if L[k] > M:
M = L[k]
return M
maxi([])
--------------------------------------------------------------------------- IndexError Traceback (most recent call last) <ipython-input-12-412a906834f3> in <module> ----> 1 maxi([]) <ipython-input-11-0d975cc57ff3> in maxi(L) 3 Renvoie le maximum des elements d’une liste de nombres L. 4 """ ----> 5 M = L[0] 6 for k in range(len(L)): 7 if L[k] > M: IndexError: list index out of range
Notre fonction ne fonctionne pas avec une liste vide...
def maxi(L):
"""
Renvoie le maximum des elements d’une liste de nombres L.
"""
if len(L) == 0:
return None
else:
M = L[0]
for k in range(len(L)):
if L[k] > M:
M = L[k]
return M
maxi([])
maxi([1, 2, 3, 4, 5, 4, 3, 2, 1])
5
maxi([5, 4, 3, 2, 1])
5
Remarque :
on peut également utiliser un parcours des éléments de la liste
L
de la façon suivante :
def maxi(L):
"""
Renvoie le maximum des elements d’une liste de nombres L.
"""
if len(L) == 0:
return None
else:
M = L[0]
for elt in L:
if elt > M:
M = elt
return M
def mini(L):
"""
Renvoie le minimum des elements d’une liste de nombres L.
"""
if len(L) == 0:
return None
else:
M = L[0]
for elt in L:
if elt < M:
M = elt
return M
def minmax(N, n, a, b):
"""
genere N listes de n entiers aleatoires compris entre a et b,
determine le maximum des elements de chacune de ces listes
et renvoie le minimum de ces maximums.
"""
if n==0:
return None
else:
Lmax=[]
for k in range(N):
L=listealeatoire(n,a,b)
M=maxi(L)
Lmax.append(M)
return mini(Lmax)
minmax(0, 10, 2, 3)
minmax(10, 0, 2, 3)
minmax(10,12,1,5)
4
def minmax(N, n, a, b):
"""
genere N listes de n entiers aleatoires compris entre a et b,
determine le maximum des elements de chacune de ces listes
et renvoie le minimum de ces maximums.
"""
if N == 0 or n == 0:
return None
else:
L = listealeatoire(n, a, b)
M = maxi(L)
m = M
for k in range(N - 1):
L = listealeatoire(n, a, b)
M = maxi(L)
if M < m:
m = M
return m
minmax(0, 10, 2, 3)
minmax(10, 0, 2, 3)
minmax(10,12,1,5)
4
def factorielle(n):
"""
Renvoie la factorielle de n.
"""
f = 1
for k in range(1, n + 1):
f = f * k
return f
def coeff(n, k):
"""
Renvoie le coefficient binomial "k parmi n"
"""
return factorielle(n) // factorielle(k) // factorielle(n - k)
coeff(0, 0)
1
coeff(3, 1)
3
coeff(9, 6)
84
[coeff(4, k) for k in range(5)]
[1, 4, 6, 4, 1]
coeff(50, 13)
354860518600
coeff(10000, 9997)
166616670000
On peut même afficher le début du triangle de Pascal :
for n in range(6):
print([coeff(n, k) for k in range(n + 1)])
[1] [1, 1] [1, 2, 1] [1, 3, 3, 1] [1, 4, 6, 4, 1] [1, 5, 10, 10, 5, 1]
def LigneSuivante(L):
"""
Reçoit une liste de nombres L
et renvoie la liste M définie comme dans l'énoncé
"""
M = [L[0]]
for k in range(1, len(L)):
M.append(L[k - 1] + L[k])
M.append(L[len(L) - 1])
return M
LigneSuivante([1, 5, 10, 10, 5, 1])
[1, 6, 15, 20, 15, 6, 1]
Une variante, avec une liste par compréhension :
def LigneSuivante(L):
"""
Reçoit une liste de nombres L
et renvoie la liste M définie comme dans l'énoncé
"""
M = [L[0]] + [L[k - 1] + L[k] for k in range(1, len(L))] + [L[len(L) - 1]]
return M
LigneSuivante([1, 5, 10, 10, 5, 1])
[1, 6, 15, 20, 15, 6, 1]
LigneSuivante([1])
[1, 1]
def Pascal(N):
"""
Affiche les N premieres lignes du triangle de Pascal.
"""
L = [1]
print(L)
for k in range(N):
L = LigneSuivante(L)
print(L)
return None
Pascal(5)
[1] [1, 1] [1, 2, 1] [1, 3, 3, 1] [1, 4, 6, 4, 1] [1, 5, 10, 10, 5, 1]
On pourrait chronométrer les 2 façons de faire pour voir que la 2ème est plus efficace : vous pouvez vous inspirer de l'exercice 6 pour faire des tests chez vous !
from math import sqrt
def estpremier(n):
"""
Teste si un nombre entier naturel est premier.
"""
if n == 0 or n == 1:
return False
for k in range(2, int(sqrt(n)) + 1):
if n % k == 0:
return False
return True
for n in range(21):
if estpremier(n):
print(n, end=' ')
print() # pour le retour a la ligne
2 3 5 7 11 13 17 19
On peut utiliser un compteur pour chaque nombre premier :
cpt = 0
for n in range(1001):
if estpremier(n):
cpt += 1
print("Il y a {} nombres premiers inférieurs (ou égaux) à 1000.".format(cpt))
Il y a 168 nombres premiers inférieurs (ou égaux) à 1000.
Python est assez souple en ce qui concerne les sommes : il peut sommer des booléens (True
vaut alors 1 et False
vaut 0). On peut donc également proposer la version suivante :
S = sum([estpremier(n) for n in range(1001)])
print("Il y a {} nombres premiers inférieurs (ou égaux) à 1000.".format(S))
Il y a 168 nombres premiers inférieurs (ou égaux) à 1000.
On va utiliser une boucle while
, jusqu'à obtenir un nombre premier :
n = 10**10
while not (estpremier(n)):
n = n + 1
print("Le plus petit nombre premier supérieur à 10**10 est {}.".format(n))
Le plus petit nombre premier supérieur à 10**10 est 10000000019.
def Crible(N):
"""
Implémente le crible d'Eratosthene
"""
C = [True for k in range(N)]
C[0] = False
C[1] = False
for k in range(2, N):
if C[k]:
for i in range(2*k,N,k):
C[i] = False
return (C)
C1 = Crible(20)
for n in range(20):
if C1[n]: # Test : n est-il premier ?
print(n, end=' ')
print()
2 3 5 7 11 13 17 19
On peut également utiliser une liste définie par compréhension (avec une condition) :
[n for n in range(20) if C1[n]]
[2, 3, 5, 7, 11, 13, 17, 19]
On retrouve également le résultat de la question 3 de l'exercice précédent :
C2 = Crible(1000)
c = 0
for n in range(1000):
if C2[n]:
c += 1
print(c)
168
ou bien également :
sum(C2)
168
from time import time
N = 100
t1 = time()
C = [estpremier(n) for n in range(N + 1)]
t2 = time()
print("Temps avec la version naïve :", t2 - t1)
t1 = time()
C = Crible(N + 1)
t2 = time()
print("Temps avec le crible d'Eratosthene :", t2 - t1)
Temps avec la version naïve : 0.0002818107604980469 Temps avec le crible d'Eratosthene : 0.00014901161193847656
N = 10**4
t1 = time()
C = [estpremier(n) for n in range(N + 1)]
t2 = time()
print("Temps avec la version naïve :", t2 - t1)
t1 = time()
C = Crible(N + 1)
t2 = time()
print("Temps avec le crible d'Eratosthene :", t2 - t1)
Temps avec la version naïve : 0.02549600601196289 Temps avec le crible d'Eratosthene : 0.004354000091552734
N = 10**5
t1 = time()
C = [estpremier(n) for n in range(N + 1)]
t2 = time()
print("Temps avec la version naïve :", t2 - t1)
t1 = time()
C = Crible(N + 1)
t2 = time()
print("Temps avec le crible d'Eratosthene :", t2 - t1)
Temps avec la version naïve : 0.1811509132385254 Temps avec le crible d'Eratosthene : 0.018087148666381836
Dès qu'on le peut, on utilise une liste par compréhension :
def diviseurs(n):
"""
reçoit un entier n positif,
et renvoie la liste de ses diviseurs autres que lui-meme.
"""
D = [k for k in range(1, n) if n % k == 0]
return D
diviseurs(12)
[1, 2, 3, 4, 6]
On peut bien sûr quand même construire la liste élément par élément :
def diviseurs(n):
"""
Reçoit un entier n positif,
et renvoie la liste de ses diviseurs autres que lui-meme.
"""
D = []
for k in range(1, n):
if n % k == 0:
D.append(k)
return D
diviseurs(30)
[1, 2, 3, 5, 6, 10, 15]
On dresse la liste de tous les nombres parfaits strictement inférieurs à $10^4$ :
P = []
N = 10**4
for n in range(N):
D = diviseurs(n)
if n == sum(D):
P.append(n)
print(P)
[0, 6, 28, 496, 8128]
Une première version, naïve et peu efficace :
A = []
N = 10**3
for a in range(N):
for b in range(a + 1, N): # pour éviter les doublons
if a == sum(diviseurs(b)) and b == sum(diviseurs(a)):
A.append((a, b))
print(A)
[(220, 284)]
Pour éviter de refaire trop de fois les mêmes calculs, on peut proposer la variante suivante :
A = []
N = 10**4
for a in range(N):
Da = sum(diviseurs(a))
for b in range(a + 1, N): # pour éviter les doublons
if b == Da:
Db = sum(diviseurs(b))
if a == Db:
A.append((a, b))
print(A)
[(220, 284), (1184, 1210), (2620, 2924), (5020, 5564), (6232, 6368)]
Remarque :
On pourrait même faire encore moins de calculs en enregistrant chaque calcul de somme des diviseurs dans une variable : ce sera possible avec ce que l'on appelle un "dictionnaire", que nous étudierons dans le prochain TP.
def jumeaux(n):
"""
Teste si n et n+2 sont premiers
"""
C = Crible(n + 3)
if C[n] and C[n + 2]:
return True
else:
return False
On peut simplifier la syntaxe pour le return
:
def jumeaux(n):
"""
Teste si n et n+2 sont premiers
"""
C = Crible(n + 3)
return C[n] and C[n + 2]
jumeaux(3)
True
jumeaux(7)
False
N = 2**20
cpt = 0 # compteur
C = Crible(N + 1)
for n in range(N - 2):
if C[n] and C[n + 2]:
# print((n,n+2)) # ça prend trop de place à l'affichage
cpt = cpt + 1
print("Il y a {} couples de nombres premiers jumeaux inférieurs à 2**20.".format(cpt))
Il y a 8535 couples de nombres premiers jumeaux inférieurs à 2**20.
Remarque :
on n'a pas utilisé la fonction
jumeaux
pour ne pas recalculer le crible à chaque fois...
C = Crible(101) # c'est une variable globale
def sommepremier(n):
"""
Teste si n peut s'écrire comme somme de 2 nombres premiers
Affiche le premier couple possible le cas échéant
"""
assert (n % 2 == 0)
for k in range(2, n // 2 + 2):
if C[k] and C[n - k]:
print("{0} = {1} + {2}".format(n, k, n - k))
return True
return False
for n in range(2, 101, 2):
sommepremier(n)
4 = 2 + 2 6 = 3 + 3 8 = 3 + 5 10 = 3 + 7 12 = 5 + 7 14 = 3 + 11 16 = 3 + 13 18 = 5 + 13 20 = 3 + 17 22 = 3 + 19 24 = 5 + 19 26 = 3 + 23 28 = 5 + 23 30 = 7 + 23 32 = 3 + 29 34 = 3 + 31 36 = 5 + 31 38 = 7 + 31 40 = 3 + 37 42 = 5 + 37 44 = 3 + 41 46 = 3 + 43 48 = 5 + 43 50 = 3 + 47 52 = 5 + 47 54 = 7 + 47 56 = 3 + 53 58 = 5 + 53 60 = 7 + 53 62 = 3 + 59 64 = 3 + 61 66 = 5 + 61 68 = 7 + 61 70 = 3 + 67 72 = 5 + 67 74 = 3 + 71 76 = 3 + 73 78 = 5 + 73 80 = 7 + 73 82 = 3 + 79 84 = 5 + 79 86 = 3 + 83 88 = 5 + 83 90 = 7 + 83 92 = 3 + 89 94 = 5 + 89 96 = 7 + 89 98 = 19 + 79 100 = 3 + 97
def goldbach(n):
"""
Teste si n peut s'écrire comme somme de 2 nombres premiers
"""
assert (n % 2 == 0)
for k in range(2, n // 2 + 2):
if C[k] and C[n - k]:
return True
return False
Ici encore, C
est une variable globale. Si on ne souhaite pas utiliser de variable globale, on pourrait la passer en paramètre de la fonction goldbach
.
N = 2**20
C = Crible(N + 2) # c'est une variable globale
k = 4
conjecture = goldbach(k)
while conjecture and k <= N:
k += 2
conjecture = goldbach(k)
print("La conjecture de Goldbach est-elle vérifiée jusqu'au rang N ?",conjecture)
La conjecture de Goldbach est-elle vérifiée jusqu'au rang N ? True