Video

Dr. Abdelwahad MAAROUF
Dr. Abdelwahad MAAROUFProf Informatique à Ministere de l'education national

merci

Informatique tronc commun, MP, premier devoir surveillé
Durée deux heures.
1 Bases de données (Mines 2017)
On modélise ici un réseau routier par un ensemble de croisements et de voies reliant ces croisements. Les
voies partent d’un croisement et arrivent à un autre croisement. Ainsi, pour modéliser une route à double
sens, on utilise deux voies circulant en sens opposés. La base de données du réseau routier est constituée des
relations suivantes :
• Croisement(id, longitude, latitude)
• Voie(id, longueur, id_croisement_debut, id_croisement_fin)
Remarque : Cela signifie que la base est constituées de deux tables : Croisement et Voie ; que les colonnes de
Croisement sont id, longitude, et latitude ; que les colonnes de Voie sont id, longueur, id_croisement_debut,
et id_croisement_fin ; et les colonnes soulignées sont les clés primaires de leur tables.
Dans la suite on considère c l’identifiant (id) d’un croisement donné.
1. (1 pt(s)) Écrire la requête SQL qui renvoie les identifiants des croisements atteignables en utilisant
une seule voie à partir du croisement ayant l’identifiant c.
SELECT id_croisement_fin
FROM Voies
WHERE id_croisement_debut = c
;
2. (2 pt(s)) Écrire la requête SQL qui renvoie les longitudes et latitudes des croisements atteignables en
utilisant une seule voie, à partir du croisement c.
SELECT Croisement.longitude, Croisement.latitude
FROM Croisement JOIN Voie ON Voie.id_croisement_fin=Croisement.id
WHERE Voie.id_croisement_debut = c
;
3. (1 pt(s)) Que renvoie la requête SQL suivante ?
SELECT V2 . id_croisement_fin
FROM Voie AS V1 JOIN Voie AS V2
ON V1 . id_croisement_fin = V2 . id_croisement_debut
WHERE V1 . id_croisement_debut = c
Cette requête renvoie les identifiants des croisements atteignables en deux voies. L’alias V1 représente la première
voie empruntée, et V2 la seconde.
4. (1 pt(s)) Préciser l’importance du AS V1 et du AS V2.
On joint ici la table Voie avec elle-même. Il est nécessaire de donner un alias à chaque copie de la table sans
quoi sql ne saura pas dans laquelle chercher les champs demandés.
5. On considère l’identifiant d d’un nouveau croisement. Écrire une requête qui renvoie tous les itinéraires
formés de deux voies permettant d’aller de c vers d, et pour chacun la longueur totale du trajet.
SELECT V1 . id_croisement_debut , V1 . id_croisement_fin , V2 . id_croisement_fin ,
V1 . longueur+V2 . longueur AS longueurDuParcours
FROM Voie as V1 JOIN Voie as V2
ON V1 . id_croisement_fin = V2 . id_croisement_debut
WHERE V1 . id_croisement_debut = c AND V2 . id_croisement_fin = d
;
1
2 Piles : algorithme de Horner
Un polynôme sera représenté par la liste de ses coefficients, par exemple [1,5,2,3] représente le polynôme
1 + 5X + 2X2
+ 3X3
. Le but est décrire une fonction d’évaluation, qui prendra en entrée un polynôme P et
un nombre x et qui calculera P(x).
Dans la suite, nous notons x un flottant, P un polynôme, n son degré, et a0, . . . , an ses coefficients.
1. (1 pt(s)) Quel est le nombre de multiplications utilisé pour calculer P(x) par l’algorithme naïf où pour
tout k ∈ N, xk
est calculé par k multiplications ?
Pour tout k ∈ J0, nK, xk
est calculé en k multiplications, donc akxk
en k + 1 multiplications, et le nombre total
de multiplications est :
n
X
k=0
k + 1 =
(n + 1)(n + 2)
2
= Θn→∞

n2

.
Ainsi la complexité est quadratique.
2. À l’aide par exemple d’une comparaison séries-intégrales, montrer que
n
X
k=1
ln(k) ∼
n→∞
n ln(n).
Soit n ∈ N∗
.
Pour tout k ∈ J1, nK et tout t ∈ [k, k + 1], ln(k) 6 ln(t) ln(k + 1), d’où, puisque la fonction ln est croissante :
ln(k) 6
Z k+1
t=k
ln(t) 6 ln(k + 1).
Notons F : x 7→ x ln(x) − x, c’est une primitive de ln, et donc :
ln(k) 6 F(k + 1) − F(k) 6 ln(k + 1).
On déduit l’encadrement de ln(k) :
Pour tout k ∈ J2, nK :
F(k) − F(k − 1) 6 ln(k) 6 F(k + 1) − F(k)
Puis en sommant :
F(n) − F(1) 6
n
X
k=2
ln(k) 6 F(n + 1) − F(2)
Comme ln(1) = 0,
Pn
k=2
ln(k) =
Pn
k=1
ln(k)
Nous voulons prouver que limn→∞
Pn
k=1
ln(k)
n ln(n)
= 1, encadrons ce quotient :
Pour tout n ∈ N∗
:
n ln(n) − n + 1
n ln(n)
6
Pn
k=1
ln(k)
n ln(n)
6
(n + 1) ln(n + 1) − (n + 1) − F(2)
n ln(n)
Ainsi le quotient est encadré par deux suites qui convergent vers 1, il converge donc lui aussi vers 1.
D’où limn→∞
Pn
k=1
ln(k)
n ln(n)
= 1, puis
Pn
k=1
ln(k) ∼
n→∞
n ln(n).
3. Donner l’ordre de grandeur du nombre de multiplications si on calcule les puissances par l’algorithme
d’exponentiation rapide vu en cours.
Pour tout k ∈ J1, nK, le calcul de xk
se fera en O(log2(k)) multiplications. Donc le nombre de multiplication
nécessaire au calcul de P(x) sera :
n
X
k=1
1 + O(log2(k)) = n +
n
X
k=1
O(log2(k)) = n + O


n
X
k=1
log2(k)

 = n +
O(n log n) = O(n log n).
4. Un élève propose cette fonction :
2
def evalue (P, x ) :
xpi=1
r e s=0
for i in range (0 , len (P) ) :
# i c i , xpi contient . . . . et res contient . . .
xpi∗=x
r e s+=P[ i ] ∗ xpi
return r e s
(a) (0,5 pt(s)) ] Combien de multiplications sont effectuées pour évaluer un polynôme de degré n ?
Il y a deux multiplications à chaque tour de boucle, donc un total de 2n multiplications.
(b) (0,5 pt(s)) À quoi sert la variable xpi ?
La variable xpi enregistre xi
pour pouvoir calculer xi+1
plus rapidement au tour de boucle prochain.
(c) (1,5 pt(s)) Il a une erreur dans ce code. La corriger, et compléter le commentaire dans la boucle.
Avec le code de l’élève, xpi contient xi+1
au moment où il est multiplié par P[i]. On calcule donc
n
X
k=0
akxk+1
. Voici une version corrigée avec l’invariant de boucle complété :
def evalue (P, x ) :
xpi=1
r e s=0
for i in range (0 , len (P) ) :
# i c i , xpi contient x∗∗ i et res contient l a somme pour k de 0 à i −1 de ak∗x∗∗k
r e s+=P[ i ] ∗ xpi
xpi∗=x
return r e s
(d) (2 pt(s)) Prouver que la fonction est correcte en utilisant la propriété en commentaire comme
invariant de boucle.
Pour tout i ∈ J0, n + 1K, notons P(i) : « au début de l’itération i (c’est-à-dire à la fin de l’itération i − 1),
xpi contient xi
et res contient
i−1
X
k=0
akxk
. »
• initialisation : au début de l’itération 0, c’est-à-dire avant de rentrer dans la boucle, xpi contient 1,
qui est bien égal à x0
, et res contient 0, qui est bien égal à
−1
X
k=0
akxk
.
• hérédité : Soit i ∈ J0, nK, supposons P(i). On aborde l’itération i + 1 de la boucle. Au début, par
P(i), xpi contient xi
et res contient
i−1
X
k=0
akxk
.
On effectue res+=P[i]*xpi, res contient alors :
i−1
X
k=0
akxk
+ ai ∗ xi
, qui vaut bien
i
X
k=0
akxk
.
Ensuite, on effectue xpi*=x, à la suite de quoi xpi contient xi
∗ i c’est-à-dire xi+1
.
Ainsi, au début de l’itération i + 1, xpi contiendra xi+1
et res contiendra
i
X
k=0
akxk
. Donc P(i + 1).
Ainsi, P est invariant de boucle : ∀i ∈ J0, n + 1K, P(i). En particulier, d’après P(n + 1), à la fin de
l’itération n, c’est-à-dire à la sortie de la boucle, res contient
n
X
k=0
akxk
, qui est le résultat renvoyé et le
résultat attendu.
5. On propose enfin l’algorithme de Horner, basé sur la remarque suivante :
P(x) = a0 +

a1 + a2x + . . . anxn−1

× x.
Pour cet algorithme, il sera plus pratique de ranger les coefficients dans une pile, le coefficient constant
étant au sommet et le coefficient de plus haut degré au fond. Ainsi, P sera représenté par [an,...,a1,a0]
et le polynôme a1 + a2X + . . . anXn−1
n’est autre que celui représenté par la pile [an,...,a1].
3
(a) Programmer l’algorithme de Horner.
Une version récursive permet de traduire immédiatement la formule proposée par l’énoncé :
def horner (P, x ) :
i f P= [ ] : return 0
else :
return P. pop ( ) + x∗ horner (P, x )
(b) Combien de multiplications sont effectuées pour calculer P(x) ?
Il y a une multiplication dans chaque appel récursif, et n appels, donc n multiplications.
3 Récursivité : résolution d’un sudoku
Nous allons étudier ici une méthode appelée backtracking qui permet de résoudre un sudoku et de
nombreux problèmes similaires.
Le principe est extrêmement basique : on choisit la case où il y a le moins chiffres possibles pour respecter
les règles du jeu, on en inscrit un, et on poursuit la résolution. Si on se rend compte que la résolution est
impossible, on efface alors le chiffre qu’on avait inscrit (c’est cette étape qui se nomme backtracking, pour
retour en arrière).
Rappel des règles et implémentation : Nous considérons une grille de format 9 × 9, qui sera repré-
sentée par un objet de type list list sous Python. Certaines cases sont déjà remplie par un chiffre de
J1, 9K. En Python, nous mettrons 0 dans les cases non remplies.
Par exemple, voici une grille complètement vide :
[[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]]
Le but est d’inscrire un chiffre de J1, 9K dans chaque case de la grille, en vérifiant les trois règles suivantes :
(i) Pour tout i ∈ J0, 8K, les chiffres inscrit sur la ligne i sont deux à deux distincts ;
(ii) Pour tout j ∈ J0, 8K, les chiffres inscrit sur la colonne j sont deux à deux distincts ;
(iii) La grille étant partagées en 9 blocs carrés de format 3 × 3, les chiffres inscrits dans chaque bloc sont
deux à deux distincts.
1. Dans un premier temps, on se concentre sur la fonction principale, qui contient le squelette de l’algo-
rithme. On supposera déjà connues les fonctions utilitaires suivantes :
• chiffresPossible telle que pour toute grille g et tout (i, j) ∈ J0, 9J2
, chiffresPossible(g,i,j)
renvoie la liste des chiffres possibles en case (i, j) de la grille g pour vérifier les trois conditions de
la règle du jeu.
• prochaineCaseARemplir telle que pour toute grille g, prochaineCaseARemplir(g) renvoie :
 None si toutes les cases sont déjà remplies (auquel cas la grille est résolue !)
 un triplet (i, j, listePoss) où (i, j) est une case ayant un minimum de possibilités et listePoss
est la liste de ces possibilités dans le cas contraire.
4
Écrire alors le programme resolution prenant en entrée une grille g et renvoyant True si cette
grille est remplissable et False sinon. En outre, ce programme remplira g au fur et à mesure, de
sorte que si il renvoie True, g soit alors complètement remplie. Par contre, si il renvoie False, la
grille devra être revenue à son état initial.
On propose la stratégie suivante :
 Utiliser le programme prochaineCaseARemplir pour repérer si la grille est déjà remplie, et
dans le cas contraire, identifier la prochaine case à aller remplir ainsi que la liste listePoss des
possibilités pour remplir cette case.
 Pour tout n ∈ listePoss, mettre n dans la case, et reappeler récursivement la fonction
resolution. Si cette fonction renvoie True c’est gagné ! Si cette fonction renvoie False c’est
qu’il n’a pas été possible de compléter la grille en y mettant n : dans ce cas, effacer n.
 Si toutes les valeurs de listePoss ont été testées sans succès, c’est qu’il n’est pas possible de
remplir la grille.
Voir le fichier .py
2. bonus : Écrire les fonctions chiffresPossibles et prochaineCaseARemplir pour obtenir un solveur
de sudoku complet.
5

Recommandé

Examen principal + Correction ASD par
Examen principal + Correction ASDExamen principal + Correction ASD
Examen principal + Correction ASDInes Ouaz
6.9K vues5 diapositives
Travaux dirigés 1: algorithme & structures de données (corrigés) par
Travaux dirigés 1: algorithme & structures de données (corrigés)Travaux dirigés 1: algorithme & structures de données (corrigés)
Travaux dirigés 1: algorithme & structures de données (corrigés)Ines Ouaz
76K vues9 diapositives
Serie2 par
Serie2Serie2
Serie2mohamed_SAYARI
24.9K vues15 diapositives
Examen principal - Algorithme & Structures de données par
Examen principal - Algorithme & Structures de donnéesExamen principal - Algorithme & Structures de données
Examen principal - Algorithme & Structures de donnéesInes Ouaz
4.4K vues2 diapositives
Algorithme & structures de données Chap III par
Algorithme & structures de données Chap IIIAlgorithme & structures de données Chap III
Algorithme & structures de données Chap IIIInes Ouaz
12.1K vues20 diapositives
Exercices_Python_Fenni_2023 -corrigé.pdf par
Exercices_Python_Fenni_2023 -corrigé.pdfExercices_Python_Fenni_2023 -corrigé.pdf
Exercices_Python_Fenni_2023 -corrigé.pdfsalah fenni
4.5K vues86 diapositives

Contenu connexe

Tendances

exercices-corriges-dalgorithmique par
exercices-corriges-dalgorithmiqueexercices-corriges-dalgorithmique
exercices-corriges-dalgorithmiquefast xp
25.6K vues24 diapositives
Diviser Pour Régner par
Diviser Pour RégnerDiviser Pour Régner
Diviser Pour RégnerMestari-Mohammed
2.3K vues51 diapositives
resume algo 2023.pdf par
resume algo 2023.pdfresume algo 2023.pdf
resume algo 2023.pdfsalah fenni
2K vues18 diapositives
Exo algo par
Exo algoExo algo
Exo algoAmaruch Benali
13.3K vues17 diapositives
Mes devoirs 4 si par
Mes devoirs 4 siMes devoirs 4 si
Mes devoirs 4 simohamed_SAYARI
27.2K vues165 diapositives
Chapitre 1 rappel par
Chapitre 1   rappelChapitre 1   rappel
Chapitre 1 rappelSana Aroussi
4.4K vues105 diapositives

Tendances(20)

exercices-corriges-dalgorithmique par fast xp
exercices-corriges-dalgorithmiqueexercices-corriges-dalgorithmique
exercices-corriges-dalgorithmique
fast xp25.6K vues
récursivité algorithmique et complexité algorithmique et Les algorithmes de tri par Yassine Anddam
récursivité algorithmique et complexité algorithmique et Les algorithmes de trirécursivité algorithmique et complexité algorithmique et Les algorithmes de tri
récursivité algorithmique et complexité algorithmique et Les algorithmes de tri
Yassine Anddam2.4K vues
Travaux dirigés 1: algorithme & structures de données par Ines Ouaz
Travaux dirigés 1: algorithme & structures de donnéesTravaux dirigés 1: algorithme & structures de données
Travaux dirigés 1: algorithme & structures de données
Ines Ouaz5.5K vues
Exercices en turbo pascal sur les nombres par salah fenni
Exercices en turbo pascal sur les nombresExercices en turbo pascal sur les nombres
Exercices en turbo pascal sur les nombres
salah fenni18.5K vues
Les algorithmes d'arithmetique par mohamed_SAYARI
Les algorithmes d'arithmetiqueLes algorithmes d'arithmetique
Les algorithmes d'arithmetique
mohamed_SAYARI13.2K vues
Algorithmique et programmation en Pascal (résumé) par salah fenni
Algorithmique et programmation en Pascal (résumé)Algorithmique et programmation en Pascal (résumé)
Algorithmique et programmation en Pascal (résumé)
salah fenni19.2K vues
Corrige exercices pascal_fenni_2018 par salah fenni
Corrige exercices pascal_fenni_2018Corrige exercices pascal_fenni_2018
Corrige exercices pascal_fenni_2018
salah fenni6.3K vues
La complexité des algorithmes récursives Géométrie algorithmique par Hajer Trabelsi
La complexité des algorithmes récursivesGéométrie algorithmiqueLa complexité des algorithmes récursivesGéométrie algorithmique
La complexité des algorithmes récursives Géométrie algorithmique
Hajer Trabelsi2.3K vues
Cours algorithmique et complexite complet par Chahrawoods Dmz
Cours algorithmique et complexite completCours algorithmique et complexite complet
Cours algorithmique et complexite complet
Chahrawoods Dmz58.3K vues
Introduction à Python - Achraf Kacimi El Hassani par Shellmates
Introduction à Python - Achraf Kacimi El HassaniIntroduction à Python - Achraf Kacimi El Hassani
Introduction à Python - Achraf Kacimi El Hassani
Shellmates4.8K vues
Serie recurrents & arithmetiques par mohamed_SAYARI
Serie recurrents & arithmetiquesSerie recurrents & arithmetiques
Serie recurrents & arithmetiques
mohamed_SAYARI10.2K vues

Similaire à Video

transparents-Algo-complexite.pdf par
transparents-Algo-complexite.pdftransparents-Algo-complexite.pdf
transparents-Algo-complexite.pdfabdallahyoubiidrissi1
7 vues34 diapositives
246242769 sequence-1-pdf par
246242769 sequence-1-pdf246242769 sequence-1-pdf
246242769 sequence-1-pdfEttaoufik Elayedi
3.4K vues60 diapositives
Exercices%20g%C3%A9n%C3%A9raux%20sur%20Python (1).pdf par
Exercices%20g%C3%A9n%C3%A9raux%20sur%20Python (1).pdfExercices%20g%C3%A9n%C3%A9raux%20sur%20Python (1).pdf
Exercices%20g%C3%A9n%C3%A9raux%20sur%20Python (1).pdfadeljaouadi
3 vues6 diapositives
Cours programmation en matlab2 (1) par
Cours programmation en matlab2 (1)Cours programmation en matlab2 (1)
Cours programmation en matlab2 (1)Guesmi Amal
2.4K vues20 diapositives
Sommation séries entières par
Sommation séries entièresSommation séries entières
Sommation séries entièresLoïc Dilly
4.5K vues7 diapositives
TD_nombres complexe.pdf par
TD_nombres complexe.pdfTD_nombres complexe.pdf
TD_nombres complexe.pdfDoukoureMAHAMADOU
45 vues4 diapositives

Similaire à Video(20)

Exercices%20g%C3%A9n%C3%A9raux%20sur%20Python (1).pdf par adeljaouadi
Exercices%20g%C3%A9n%C3%A9raux%20sur%20Python (1).pdfExercices%20g%C3%A9n%C3%A9raux%20sur%20Python (1).pdf
Exercices%20g%C3%A9n%C3%A9raux%20sur%20Python (1).pdf
adeljaouadi3 vues
Cours programmation en matlab2 (1) par Guesmi Amal
Cours programmation en matlab2 (1)Cours programmation en matlab2 (1)
Cours programmation en matlab2 (1)
Guesmi Amal2.4K vues
Sommation séries entières par Loïc Dilly
Sommation séries entièresSommation séries entières
Sommation séries entières
Loïc Dilly4.5K vues
Chapitre 2 complexité par Sana Aroussi
Chapitre 2 complexitéChapitre 2 complexité
Chapitre 2 complexité
Sana Aroussi7.4K vues
124776153 td-automatique-1 a-jmd-2011 par sunprass
124776153 td-automatique-1 a-jmd-2011124776153 td-automatique-1 a-jmd-2011
124776153 td-automatique-1 a-jmd-2011
sunprass8.1K vues
Traitement des données massives (INF442, A4) par Frank Nielsen
Traitement des données massives (INF442, A4)Traitement des données massives (INF442, A4)
Traitement des données massives (INF442, A4)
Frank Nielsen178 vues
Chapitre 2 -Complexité des problèmes avec correction.pdf par MbarkiIsraa
Chapitre 2 -Complexité des problèmes avec correction.pdfChapitre 2 -Complexité des problèmes avec correction.pdf
Chapitre 2 -Complexité des problèmes avec correction.pdf
MbarkiIsraa475 vues
CAPES maths 2019 composition 1 (option informatique) par Dany-Jack Mercier
CAPES maths 2019 composition 1 (option informatique)CAPES maths 2019 composition 1 (option informatique)
CAPES maths 2019 composition 1 (option informatique)
Chapitre 2 plus court chemin par Sana Aroussi
Chapitre 2 plus court cheminChapitre 2 plus court chemin
Chapitre 2 plus court chemin
Sana Aroussi1.7K vues
Epreuve de mathématiques informatique (modélisation) Agro/Véto BCPST 2017 par Ahmed Ammar Rebai PhD
Epreuve de mathématiques informatique (modélisation) Agro/Véto BCPST 2017Epreuve de mathématiques informatique (modélisation) Agro/Véto BCPST 2017
Epreuve de mathématiques informatique (modélisation) Agro/Véto BCPST 2017

Video

  • 1. Informatique tronc commun, MP, premier devoir surveillé Durée deux heures. 1 Bases de données (Mines 2017) On modélise ici un réseau routier par un ensemble de croisements et de voies reliant ces croisements. Les voies partent d’un croisement et arrivent à un autre croisement. Ainsi, pour modéliser une route à double sens, on utilise deux voies circulant en sens opposés. La base de données du réseau routier est constituée des relations suivantes : • Croisement(id, longitude, latitude) • Voie(id, longueur, id_croisement_debut, id_croisement_fin) Remarque : Cela signifie que la base est constituées de deux tables : Croisement et Voie ; que les colonnes de Croisement sont id, longitude, et latitude ; que les colonnes de Voie sont id, longueur, id_croisement_debut, et id_croisement_fin ; et les colonnes soulignées sont les clés primaires de leur tables. Dans la suite on considère c l’identifiant (id) d’un croisement donné. 1. (1 pt(s)) Écrire la requête SQL qui renvoie les identifiants des croisements atteignables en utilisant une seule voie à partir du croisement ayant l’identifiant c. SELECT id_croisement_fin FROM Voies WHERE id_croisement_debut = c ; 2. (2 pt(s)) Écrire la requête SQL qui renvoie les longitudes et latitudes des croisements atteignables en utilisant une seule voie, à partir du croisement c. SELECT Croisement.longitude, Croisement.latitude FROM Croisement JOIN Voie ON Voie.id_croisement_fin=Croisement.id WHERE Voie.id_croisement_debut = c ; 3. (1 pt(s)) Que renvoie la requête SQL suivante ? SELECT V2 . id_croisement_fin FROM Voie AS V1 JOIN Voie AS V2 ON V1 . id_croisement_fin = V2 . id_croisement_debut WHERE V1 . id_croisement_debut = c Cette requête renvoie les identifiants des croisements atteignables en deux voies. L’alias V1 représente la première voie empruntée, et V2 la seconde. 4. (1 pt(s)) Préciser l’importance du AS V1 et du AS V2. On joint ici la table Voie avec elle-même. Il est nécessaire de donner un alias à chaque copie de la table sans quoi sql ne saura pas dans laquelle chercher les champs demandés. 5. On considère l’identifiant d d’un nouveau croisement. Écrire une requête qui renvoie tous les itinéraires formés de deux voies permettant d’aller de c vers d, et pour chacun la longueur totale du trajet. SELECT V1 . id_croisement_debut , V1 . id_croisement_fin , V2 . id_croisement_fin , V1 . longueur+V2 . longueur AS longueurDuParcours FROM Voie as V1 JOIN Voie as V2 ON V1 . id_croisement_fin = V2 . id_croisement_debut WHERE V1 . id_croisement_debut = c AND V2 . id_croisement_fin = d ; 1
  • 2. 2 Piles : algorithme de Horner Un polynôme sera représenté par la liste de ses coefficients, par exemple [1,5,2,3] représente le polynôme 1 + 5X + 2X2 + 3X3 . Le but est décrire une fonction d’évaluation, qui prendra en entrée un polynôme P et un nombre x et qui calculera P(x). Dans la suite, nous notons x un flottant, P un polynôme, n son degré, et a0, . . . , an ses coefficients. 1. (1 pt(s)) Quel est le nombre de multiplications utilisé pour calculer P(x) par l’algorithme naïf où pour tout k ∈ N, xk est calculé par k multiplications ? Pour tout k ∈ J0, nK, xk est calculé en k multiplications, donc akxk en k + 1 multiplications, et le nombre total de multiplications est : n X k=0 k + 1 = (n + 1)(n + 2) 2 = Θn→∞ n2 . Ainsi la complexité est quadratique. 2. À l’aide par exemple d’une comparaison séries-intégrales, montrer que n X k=1 ln(k) ∼ n→∞ n ln(n). Soit n ∈ N∗ . Pour tout k ∈ J1, nK et tout t ∈ [k, k + 1], ln(k) 6 ln(t) ln(k + 1), d’où, puisque la fonction ln est croissante : ln(k) 6 Z k+1 t=k ln(t) 6 ln(k + 1). Notons F : x 7→ x ln(x) − x, c’est une primitive de ln, et donc : ln(k) 6 F(k + 1) − F(k) 6 ln(k + 1). On déduit l’encadrement de ln(k) : Pour tout k ∈ J2, nK : F(k) − F(k − 1) 6 ln(k) 6 F(k + 1) − F(k) Puis en sommant : F(n) − F(1) 6 n X k=2 ln(k) 6 F(n + 1) − F(2) Comme ln(1) = 0, Pn k=2 ln(k) = Pn k=1 ln(k) Nous voulons prouver que limn→∞ Pn k=1 ln(k) n ln(n) = 1, encadrons ce quotient : Pour tout n ∈ N∗ : n ln(n) − n + 1 n ln(n) 6 Pn k=1 ln(k) n ln(n) 6 (n + 1) ln(n + 1) − (n + 1) − F(2) n ln(n) Ainsi le quotient est encadré par deux suites qui convergent vers 1, il converge donc lui aussi vers 1. D’où limn→∞ Pn k=1 ln(k) n ln(n) = 1, puis Pn k=1 ln(k) ∼ n→∞ n ln(n). 3. Donner l’ordre de grandeur du nombre de multiplications si on calcule les puissances par l’algorithme d’exponentiation rapide vu en cours. Pour tout k ∈ J1, nK, le calcul de xk se fera en O(log2(k)) multiplications. Donc le nombre de multiplication nécessaire au calcul de P(x) sera : n X k=1 1 + O(log2(k)) = n + n X k=1 O(log2(k)) = n + O   n X k=1 log2(k)   = n + O(n log n) = O(n log n). 4. Un élève propose cette fonction : 2
  • 3. def evalue (P, x ) : xpi=1 r e s=0 for i in range (0 , len (P) ) : # i c i , xpi contient . . . . et res contient . . . xpi∗=x r e s+=P[ i ] ∗ xpi return r e s (a) (0,5 pt(s)) ] Combien de multiplications sont effectuées pour évaluer un polynôme de degré n ? Il y a deux multiplications à chaque tour de boucle, donc un total de 2n multiplications. (b) (0,5 pt(s)) À quoi sert la variable xpi ? La variable xpi enregistre xi pour pouvoir calculer xi+1 plus rapidement au tour de boucle prochain. (c) (1,5 pt(s)) Il a une erreur dans ce code. La corriger, et compléter le commentaire dans la boucle. Avec le code de l’élève, xpi contient xi+1 au moment où il est multiplié par P[i]. On calcule donc n X k=0 akxk+1 . Voici une version corrigée avec l’invariant de boucle complété : def evalue (P, x ) : xpi=1 r e s=0 for i in range (0 , len (P) ) : # i c i , xpi contient x∗∗ i et res contient l a somme pour k de 0 à i −1 de ak∗x∗∗k r e s+=P[ i ] ∗ xpi xpi∗=x return r e s (d) (2 pt(s)) Prouver que la fonction est correcte en utilisant la propriété en commentaire comme invariant de boucle. Pour tout i ∈ J0, n + 1K, notons P(i) : « au début de l’itération i (c’est-à-dire à la fin de l’itération i − 1), xpi contient xi et res contient i−1 X k=0 akxk . » • initialisation : au début de l’itération 0, c’est-à-dire avant de rentrer dans la boucle, xpi contient 1, qui est bien égal à x0 , et res contient 0, qui est bien égal à −1 X k=0 akxk . • hérédité : Soit i ∈ J0, nK, supposons P(i). On aborde l’itération i + 1 de la boucle. Au début, par P(i), xpi contient xi et res contient i−1 X k=0 akxk . On effectue res+=P[i]*xpi, res contient alors : i−1 X k=0 akxk + ai ∗ xi , qui vaut bien i X k=0 akxk . Ensuite, on effectue xpi*=x, à la suite de quoi xpi contient xi ∗ i c’est-à-dire xi+1 . Ainsi, au début de l’itération i + 1, xpi contiendra xi+1 et res contiendra i X k=0 akxk . Donc P(i + 1). Ainsi, P est invariant de boucle : ∀i ∈ J0, n + 1K, P(i). En particulier, d’après P(n + 1), à la fin de l’itération n, c’est-à-dire à la sortie de la boucle, res contient n X k=0 akxk , qui est le résultat renvoyé et le résultat attendu. 5. On propose enfin l’algorithme de Horner, basé sur la remarque suivante : P(x) = a0 + a1 + a2x + . . . anxn−1 × x. Pour cet algorithme, il sera plus pratique de ranger les coefficients dans une pile, le coefficient constant étant au sommet et le coefficient de plus haut degré au fond. Ainsi, P sera représenté par [an,...,a1,a0] et le polynôme a1 + a2X + . . . anXn−1 n’est autre que celui représenté par la pile [an,...,a1]. 3
  • 4. (a) Programmer l’algorithme de Horner. Une version récursive permet de traduire immédiatement la formule proposée par l’énoncé : def horner (P, x ) : i f P= [ ] : return 0 else : return P. pop ( ) + x∗ horner (P, x ) (b) Combien de multiplications sont effectuées pour calculer P(x) ? Il y a une multiplication dans chaque appel récursif, et n appels, donc n multiplications. 3 Récursivité : résolution d’un sudoku Nous allons étudier ici une méthode appelée backtracking qui permet de résoudre un sudoku et de nombreux problèmes similaires. Le principe est extrêmement basique : on choisit la case où il y a le moins chiffres possibles pour respecter les règles du jeu, on en inscrit un, et on poursuit la résolution. Si on se rend compte que la résolution est impossible, on efface alors le chiffre qu’on avait inscrit (c’est cette étape qui se nomme backtracking, pour retour en arrière). Rappel des règles et implémentation : Nous considérons une grille de format 9 × 9, qui sera repré- sentée par un objet de type list list sous Python. Certaines cases sont déjà remplie par un chiffre de J1, 9K. En Python, nous mettrons 0 dans les cases non remplies. Par exemple, voici une grille complètement vide : [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]] Le but est d’inscrire un chiffre de J1, 9K dans chaque case de la grille, en vérifiant les trois règles suivantes : (i) Pour tout i ∈ J0, 8K, les chiffres inscrit sur la ligne i sont deux à deux distincts ; (ii) Pour tout j ∈ J0, 8K, les chiffres inscrit sur la colonne j sont deux à deux distincts ; (iii) La grille étant partagées en 9 blocs carrés de format 3 × 3, les chiffres inscrits dans chaque bloc sont deux à deux distincts. 1. Dans un premier temps, on se concentre sur la fonction principale, qui contient le squelette de l’algo- rithme. On supposera déjà connues les fonctions utilitaires suivantes : • chiffresPossible telle que pour toute grille g et tout (i, j) ∈ J0, 9J2 , chiffresPossible(g,i,j) renvoie la liste des chiffres possibles en case (i, j) de la grille g pour vérifier les trois conditions de la règle du jeu. • prochaineCaseARemplir telle que pour toute grille g, prochaineCaseARemplir(g) renvoie : None si toutes les cases sont déjà remplies (auquel cas la grille est résolue !) un triplet (i, j, listePoss) où (i, j) est une case ayant un minimum de possibilités et listePoss est la liste de ces possibilités dans le cas contraire. 4
  • 5. Écrire alors le programme resolution prenant en entrée une grille g et renvoyant True si cette grille est remplissable et False sinon. En outre, ce programme remplira g au fur et à mesure, de sorte que si il renvoie True, g soit alors complètement remplie. Par contre, si il renvoie False, la grille devra être revenue à son état initial. On propose la stratégie suivante : Utiliser le programme prochaineCaseARemplir pour repérer si la grille est déjà remplie, et dans le cas contraire, identifier la prochaine case à aller remplir ainsi que la liste listePoss des possibilités pour remplir cette case. Pour tout n ∈ listePoss, mettre n dans la case, et reappeler récursivement la fonction resolution. Si cette fonction renvoie True c’est gagné ! Si cette fonction renvoie False c’est qu’il n’a pas été possible de compléter la grille en y mettant n : dans ce cas, effacer n. Si toutes les valeurs de listePoss ont été testées sans succès, c’est qu’il n’est pas possible de remplir la grille. Voir le fichier .py 2. bonus : Écrire les fonctions chiffresPossibles et prochaineCaseARemplir pour obtenir un solveur de sudoku complet. 5