0% ont trouvé ce document utile (0 vote)
14 vues5 pages

IC2 DS 01 Handout

Le document présente une série d'exercices de programmation en Python, couvrant des concepts tels que la factorielle, le pgcd, la recherche dichotomique, et la fusion de listes. Il inclut également des exercices sur des requêtes SQL et des méthodes numériques comme le schéma d'Euler. Enfin, il aborde des problèmes de Project Euler, demandant des solutions algorithmiques et des explications sur les étapes de résolution.

Transféré par

Mohamed Gossoni
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
14 vues5 pages

IC2 DS 01 Handout

Le document présente une série d'exercices de programmation en Python, couvrant des concepts tels que la factorielle, le pgcd, la recherche dichotomique, et la fusion de listes. Il inclut également des exercices sur des requêtes SQL et des méthodes numériques comme le schéma d'Euler. Enfin, il aborde des problèmes de Project Euler, demandant des solutions algorithmiques et des explications sur les étapes de résolution.

Transféré par

Mohamed Gossoni
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Informatique commune - Lycée du parc 2ème année

 
 DS 1 
Exercice 1. Écrire les fonctions factorielle(n) (itératif) et factorielle_rec(n) (récursif). Quelle
est la complexité de ces fonctions ? Donner un inconvénient de la version récursive : en python, pour
quelles valeurs de n aura-t-on un problème ?

Exercice 2. Écrire une fonction en python permettant de calculer le pgcd de deux entiers positifs a et
b.
Écrire une fonction récursive permettant de calculer le plus grand diviseur commun d’un ensemble
de nombres (donnés dans un tableau) : pgcd_tableau(t). On ne fera pas attention à la complexité.

Exercice 3. Écrire une fonction permettant de déterminer si un entier n est premier. De quel type est
la valeur renvoyée ? Expliquer les optimisations que vous avez faites.

Exercice 4. On considère deux listes d’entiers (type list en Python), u et v, déjà triées dans l’ordre
croissant. Écrire une fonction fusion(u, v) qui renvoie la fusion des deux listes u et v (triée aussi).
Quelle est la complexité de votre fonction ?
fusion([1, 7, 7, 12], [-1, 2, 11, 12, 13]) doit renvoyer [-1, 1, 2, 7, 7, 11, 12, 12, 13]

Exercice 5. Soit un point M du plan de coordonnées (x, y) dans un repère orthonormé direct (O, I, J).
Écrire un une fonction trigo(x, y) permettant de calculer cos((OI,~ OM)).
~ On pourra utiliser la fonc-
tion sqrt du module math qui renvoie la racine carrée d’un flottant.

Exercice 6. [Récursivité] Écrire une fonction dichotomie(t, x) qui cherche si l’élément x est présent
dans un tableau (trié) t (type list) par dichotomie en utilisant une fonction récursive. Quelle est la
complexité de votre fonction : attention le slicing t [a : b] a pour complexité Θ(b − a).

Exercice 7. import matplotlib.pyplot as plt


Écrire un bloc de code permettant d’afficher une courbe représentative de la fonction f : x → x 3 + 1
sur [0; 1] (avec la précision que vous voulez). Commentez votre code.

Exercice 8. La fonction random() du module random renvoie un flottant aléatoire dans [0; 1[. En dé-
duire une fonction python alea(n) qui renvoie un entier tiré au hasard dans [[1; n]] et écrire un bloc de
code qui demande un entier k à l’utilisateur (avec input) et affiche (avec print) un entier tiré au hasard
dans ‚1; kƒ.

Exercice 9. SQL : On considère un nuage de points associés à des prénoms stockés dans une base de
données. Un prénom peut apparaître plusieurs fois.
Le schéma relationnel associé est

poi nt s{i d : i nt eg er ; x : i nt eg er ; y : i nt eg er ; pr enom : t ext }

1. Expliquer à quoi sert le champ i d et ce que signifie le fait qu’il soit souligné.
2. Écrire une requête SQL qui donne la plus grande valeur de x et la plus petite valeur de y qui
apparaissent dans la base de donnée.
3. Écrire une requête SQL qui compte combien de points sont associés à chaque prénom.
4. Écrire une requête SQL qui donne les coordonnées du point moyen (moyenne des x i , moyenne
des y i ). Remarque : ce point n’appartient pas forcément à l’ensemble des points dans la base de donnée.
5. Écrire une requête SQL qui donne les noms associés aux points les plus à droite du nuage de
points.
6. Écrire une requête SQL qui donne les coordonnées du point le plus éloigné de l’origine.

Exercice 10. Expliquer succintement le schéma d’Euler explicite.


Écrire une fonction python euler(F, y0, temps) qui applique le schéma d’Euler explicite à l’équation
différentielle d’ordre 1 : y 0 = F(y, t ) aux temps t 0 , t 1 , ...t n−1 (liste temps) avec y(t 0 ) = y 0

1
Écrire la fonction python F(y, t) qui correspond à l’équation différentielle y 00 (t ) − 3y 0 (t ) + 4t = 5

Exercice 11. [Exponentiation rapide]

def expo_rapide(x, n)
resultat, p, m = 1, x, n
while m > 0:
if m % 2 == 0:
resultat, p, m = resultat, p * p, m // 2
else:
resultat, p, m = resultat * p, p * p, (m - 1) // 2
return resultat
Montrer que l’égalité x n = r esul t at × p m est un invariant de boucle (pour la seule boucle whi l e
du programme), c’est à dire qu’elle est vraie avant la première itération, et que si elle est vraie au début
d’une itération alors elle est aussi vraie à la fin. On pourra noter r esul t at , p, m les variables en début
d’itération et r ésul t at 0 , p 0 , m 0 les variables en fin d’itération. Conclure.
Quelle est la complexité de cette fonction ?

Exercice 12. [Projet Euler 12] The sequence of triangle numbers is generated by adding the natural
numbers. So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28. The first ten terms would be:
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
Let us list the factors of the first seven triangle numbers:

1: 1
3: 1,3
6: 1,2,3,6
10: 1,2,5,10
15: 1,3,5,15
21: 1,3,7,21
28: 1,2,4,7,14,28

We can see that 28 is the first triangle number to have over five divisors.
What is the value of the first triangle number to have over five hundred divisors?
Résoudre ce problème à l’aide de python en expliquant les étapes.

Exercice 13. Écrire une fonction permettant de tester si deux piles sont égales (mêmes éléments
dans le même ordre). On supposera qu’on sait manipuler les piles avec les fonctions creer_pile(),
est_vide(p), empiler(p, x), depiler(p), sommet(p).

Exercice 14. Écrire une fonction partage(p) prenant en entrée une pile p et renvoyant une pile con-
tenant les mêmes éléments, mais où tous les éléments strictement positifs sont "au dessus" de tous les
éléments négatifs. On ne demande pas de laisser p intacte.

Exercice 15. [Project Euler 5] 2520 is the smallest number that can be divided by each of the numbers
from 1 to 10 without any remainder.
What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?
Écrire un programme python qui permet de résoudre ce problème.

Exercice 16. Reprendre l’exercice sur les nombres triangulaires (Project Euler 12) en remarquant que
n(n+1)
2 est le produit de deux nombres premiers entre eux (distinguer les cas)

Exercice 17. Reprendre tous les exercices précédents en Scilab ;-)

2
ou, plus simple, une version itérative (pas demandé ici).

def pgcd_general(tabl): # Version itérative, pas demandée


DS 01 - Algorithmes / Récursivité p = 0
for x in tabl:
p = pgcd(p, x)
return p

Exercice 3
Exercice 1
import math
def factorielle_rec(n): def est_premier(n):
if n == 0: # cas de base assert n >= 0, "On suppose n positif"
return 1 if n <= 1: # Cas particulier : à vérifier !
else: return False
return n * factorielle_rec(n - 1) for d in range(2, int(math.sqrt(n)) + 1):
if n % d == 0:
def factorielle_it(n): return False
produit = 1 return True
for i in range(2, n + 1): # attention aux bornes : de 2 à n inclus
produit *= i
return produit • On renvoie un booléen (True ou False)
• On peut se limiter à rechercher des diviseurs potentiels inférieurs (au sens large) à sqrt(n)
Ces deux fonctions sont de complexité Θ(n). Avec la version récursive, il peut se produire un dépassement de la pile d’exécution • Dès qu’on trouve un diviseur de n, on peut renvoyer directement False
(n > 1000 environ)

Exercice 4
Exercice 2
Les listes sont déjà triées dans l’ordre croissant. Remarque : il suffit de comparer le premier élément de chaque liste :
def pgcd(a, b):
"""Algorithme d'Euclide pour calculer le pgcd de deux entiers."""
• si ils sont égaux, cette valeur fait partie de l’intersection
if b == 0:
• sinon on supprime le plus petit de deux et on recommence
return a
else: • il ne faut pas supprimer l’élément dans les deux listes !
return pgcd(b, a % b) • Ici le fait d’utiliser le slicing fait exploser la complexité : cf. exercice sur la dichotomie.

def pgcd_it(a, b): def fusion(a, b):


while b != 0: if a == [] or b == []:
a, b = b, a % b return []
return a elif a[0] < b[0]:
return [a[0]] + fusion(a[1:], b)
On peut aussi utiliser des soustractions, mais il faut faire attention à échanger a et b si a < b. . . else:
return [b[0]] + fusion(a, b[1:])
def pgcd_general(tabl):
assert len(tabl) > 0, "On attend un tableau avec au moins un élément."
Idem, ici la complexité est en O(|a|2 + |b|2 ). On peut faire mieux : cf. la “fusion” itérative du tri fusion vue en cours.
if len(tabl) == 1:
return tabl[0]
else:
return pgcd(tabl[0], pgcd_general(tab[1:]) Exercice 5
La version récursive ci-dessus n’est pas terrible en termes de complexité à cause du slicing. On pourrait écrire une fonction qui def trigo(x, y):
prend en entrée le tableau et un indice. . . assert not (x == 0 and y == 0)
return x / sqrt(x ** 2 + y ** 2)
def pgcd_aux(t, i, res):
if i == len(t):
(Faire un schéma)
return res
return pgcd_aux(t, i + 1, pgcd(t[i], res))

def pgcd_general(t):
return pgcd_aux(t, 0, 0) # On initisalise le pgcd à 0

1 2
Exercice 6 Exercice 9
def dichotomie(t, x): C’est un identifiant qui permet de référencer chaque ligne de manière unique : c’est une clé primaire.
if len(t) == 0: return False
m = len(t) // 2
if x == t[m]: SELECT MAX(x), MIN(y) FROM base
return True
elif x < t[m]: -- C'est important de garder le prénom !
return dichotomie(t[:m], x) # jusqu'à m exclu SELECT COUNT(*), prenom FROM base GROUP BY prenom
else:
return dichotomie(t[m + 1:], x) # à partir de m exclu SELECT AVG(x), AVG(y) FROM base

Cette version fonctionne bien, mais le slicing est très couteux : pour un tableau de taille n = 2k , on recopie : 2k−1 +2k−2 +...+20 = -- On peut aussi utiliser HAVING
2k − 1 = O(n) éléments. Donc la complexité de cette fonction est en O(n) contre O(ln(n)) attendu : SELECT prenom FROM base WHERE x = (SELECT MAX(x) FROM base)

def dicho(x, t, i, j): # oui, vous pouvez l'appler 'aux' :s -- Même principe, c'est un peu galère...
"""Recherche dichotomique de x dans t SELECT x, y, x * x + y * y AS dist_carre FROM base WHERE dist_carre = (SELECT MAX(x * x + y * y) FROM base)
entre l'indice i inclus et j exclu (convention)"""
if i == j:
return False Exercice 10
m = (i + j) // 2
if x == t[m]: Le schéma d’Euler explicite permet de résoudre numériquement une équation différentielle donnée par y 0 = F (y, t) en calculant
return True des valeurs yk aux temps tk de proche en proche en utilisant l’approximation : yk+1 = yk + (tk+1 − tk ) × F (yk , tk ) (c’est ça le
elif x < t[m]: schéma d’Euler explicite)
return dicho(x, t, i, m)
else:
def euler(F, y0, temps):
return dicho(x, t, m + 1, j)
LY = [y_0]
for i in range(1, len(temps)): # on ne prend pas le premier élément
def dichotomie(t, x):
LY.append(LY[-1] + (temps[i] - temps[i - 1]) * F(LY[-1], temps[i - 1]))
return dicho(t, x, 0, len(t)) # jusqu'à len(t) exclu
return LY

On ne recopie jamais t. Chaque appel à dichotomie fait un nombre borné d’opérations, plus un appel récursif. pour n = 2k , on a
Attention : pour que ça fonctionne à un ordre supérieur à 1, il faut que, dans LY.append(... + ... * ...), le produit et la
C(n) = 1 + C( n2 ) d’ou C(n) = O(ln(n))
somme se fassent bien terme à terme. . . par exemple en utilisant numpy
Après, il faut définir la fonction F (Y, t) pour que ça corresponde au problème à résoudre.
Exercice 7
def F(Y, t): # y''= 3*y' - 4*t + 5
import matplotlib.pyplot as plt, numpy as np y, yp = Y
return (yp, 3*yp-4*t+5)
def f(x):
return (x ** 3 + 1) / x
Exercice 11
LX = (np.linspace(0, 1, 100))
LY = [f(x) for x in LX] # plus simple que d'autred méthodes Avant la première itération, on a : resulat × pm = 1 × xn = xn
plt.plot(LX, LY) # à connaitre !
plt.show() Si on suppose qu’au début d’une itération on bien resultat × pm = xn , alors à la fin de l’itération, on a :

m0
• Si m est pair : resultat0 × p0 = resultat × (p ∗ p)m/2 = resultat × pm = xn
Exercice 8 • Si m est impair : resultat0 × p0
m0
= (resultat ∗ p) × (p ∗ p)(m−1)/2 = resultat × pm = xn

import random
On peut en déduire qu’à la fin de la boucle (i.e. pour m = 0), on a resultat = resultat × p0 = xn
def alea(n):
return int(random.random() * n) + 1 # n valeurs possibles
Exercice 12
k = int(input("Entrez un entier k :")) # à connaître !
print(alea(k)) On peut utiliser une méthode bruteforce en calculant tous les nombres triangulaires et pour chacun son nombre de diviseurs par
exemple avec :

3 4
def nbdiv(n):
if n == 1:
return 1
nb, racine = 0, int(math.sqrt(n))
for d in range(racine + 1):
if n % d == 0:
nb += 2 # on a trouvé 2 diviseurs : d et (n // d)
if racine * racine = n:
nb -= 1 # Si c'est un carré parfait, on a compté deux fois la racine
return nb

ou faire mieux (Ex 16)

Exercice 13
def egalite(pile1, pile2):
while not est_vide(pile1) and not est_vide(pile2):
if depiler(pile1) != depiler(pile2):
return False
return est_vide(pile1) and est_vide(pile2)

Exercice 14
def partage(pile):
positif = creer_pile()
negatif = creer_pile()
while not est_vide(pile):
element = depiler(pile)
if element > 0:
empiler(positif, element)
else:
empile(negatif, element)
resultat = creer_pile()
while not est_vide(negatif):
empiler(resultat, depiler(negatif))
while not est_vide(positif):
empiler(resultat, depiler(positif))
return resultat

Exercice 15
def euler15(): # Plusieurs méthodes, en particulier on peut calculer le ppcm...
p = 1
for i in range(1, 20 + 1):
p *= i // pgcd(p, i)
return p

Exercice 16
Selon la parité de n, comme (n et n+1 2 ) ou ( 2 et n + 1) sont premiers entre eux, on peut faire le produit de leur nombre de
n

diviseurs respectifs en utilisant la fonction nbdiv précédente. C’est beaucoup plus rapide que la méthode directe !

Vous aimerez peut-être aussi