Énoncé - SourceSup

publicité
M1 MEEF SD maths option info
Devoir Surveillé Semestre 1
Ce sujet comporte deux problèmes indépendants ainsi qu’une annexe présentant entre autres un
certain nombre de fonctions utiles à la rédaction des programmes en langage Python.
Lorsqu’il est demandé d’écrire un programme ou un algorithme dans une question, celui-ci devra
systématiquement être rédigé en Python.
Les résultats des questions pourront être réutilisés ainsi que les différentes fonctions demandées non
traitées au cours du problème.
L’usage de la calculatrice est interdit.
1
1.1
Systèmes de numération
Contexte et rappels
Le but de ce sujet est l’étude de différents aspects algorithmiques et théoriques de la représentation
des nombres. Dans tout le sujet, B désigne un nombre entier compris entre 2 et 10, et est appelé la base
de numération, ou simplement la base.
Habituellement, les nombres entiers compris entre 0 et B − 1 sont appelés chiffres en base B, ou
simplement les chiffres.
Soit Σ l’ensemble constitué des chiffres en base B. On dit qu’un mot non vide ak . . . a0 sur Σ représente
le nombre entier n ∈ N en base B si
k
X
n=
ai B i
i=0
Notons qu’il y a une légère ambiguïté de notations. Par exemple, 7 est à la fois un nombre, un symbole
de l’alphabet Σ (quand B > 8), et un mot sur Σ qui représente l’entier 7 en toute base B > 8. Par
convention, le mot vide représente l’entier zéro. Noter qu’avec la définition donnée ici, plusieurs mots
peuvent représenter le même entier. Par exemple, en base dix, les mots 12, 012 et 0000012 représentent
tous le nombre entier douze.
On admet le théorème classique suivant : pour tout entier n ∈ N, il existe un unique mot en base
B, appelé la plus petite représentation en base B de n, ne commençant pas par zéro, et représentant n.
Noter que la plus petite représentation de zéro est le mot vide (en toute base).
On rappelle que si n ∈ N et d ∈ N∗ sont deux entiers naturels, alors il existe un unique couple d’entiers
naturels (q, r) tel que 0 6 r 6 d − 1 et n = qd + r. L’entier q est le quotient de n par d, et l’entier r est
le reste dans la division euclidienne de n par d. On définit l’opération modulo, notée mod , par :
n mod d := r
1.2
Numération avec des chiffres négatifs
Dans cette partie, B = 3, et on définit les chiffres en base B comme étant les nombres entiers 0,
1 et −1. On remarque donc qu’il y a un chiffre négatif, contrairement aux systèmes de numération
usuels. Soit Σ l’alphabet constitué des chiffres en base B. On dit qu’un mot non vide ak . . . a0 sur Σ
représente le nombre entier n ∈ Z en base B si
n=
k
X
ai B i
i=0
Par convention, le mot vide représente l’entier zéro. Le chiffre −1 sera noté 1̄ pour simplifier l’écriture
et la lecture des mots. Ainsi, le mot 11̄01̄1̄11 représente l’entier 36 − 35 − 33 − 32 + 3 + 1 = 454.
1
Pour les algorithmes demandés ci-dessous, la représentation d’un nombre entier sera implémentée
comme une liste Python d’entiers contenant les chiffres. Il est plus commode pour traiter les nombres
de commencer par le dernier chiffre (chiffre des unités), on les stockera donc « de droite à gauche » dans
la liste. Plus précisemment, la représentation ak . . . a0 sera stockée dans une liste L telle que L[0] = a0 ,
. . . , L[k] = ak .
Question 1.1 Donner une représentation pour chaque nombre entier de [−5, 5].
Question 1.2 Montrer que pour tout entier n ∈ Z, il existe un unique mot sur Σ, appelé la plus petite
représentation de n, ne commençant pas par zéro, et représentant n.
Donner un algorithme pour calculer les chiffres de la plus petite représentation d’un entier n quelconque (cet algorithme peut être utilisé comme preuve d’existence de la décomposition).
1.3
Opérations avec des chiffres négatifs
Pour les quatre questions qui suivent, on demande des algorithmes qui calculent directement à partir
des chiffres de représentations, sur le modèle de l’algorithme d’addition des représentations en base
10 enseigné à l’école primaire. En particuler, il est interdit d’utiliser les fonctions multiplications et
exponentiation du langage, et a fortiori toute fonction plus évoluée. Seules l’addition et les structures de
contrôle élémentaires (tests, boucles, ...) sont autorisées. L’efficacité des algorithmes sera prise en compte
pour la notation.
Question 1.3 Donner un algorithme qui prend en entrée une liste représentant un nombre entier, et
renvoie une liste représentant son opposé.
Question 1.4 Donner un algorithme qui prend en entrée une liste représentant un nombre entier et
renvoie une liste représentant son successeur (le même entier + 1).
Question 1.5 Donner un algorithme qui prend en entrée deux listes représentant deux nombres entiers
et renvoie la représentation de leur somme.
Question 1.6 Donner un algorithme qui prend en entrée deux listes représentant deux nombres entiers
et renvoie la représentation de leur différence.
2
Grands rectangles
Ce problème porte sur la détection de zones rectangulaires monochromatiques dans une image. Imaginons par exemple une image en noir et blanc, le problème est d’en trouver la plus grande zone noire.
Ces zones monochromatiques peuvent être représentées de manière compacte en retenant les cordonnées
des coins et la couleur interne. En décomposant une image selon ces grands rectangles, il est possible
de la compresser efficacement, les zones monochromatiques pouvant être représentées de manière très
compacte.
2.1
Faisabilité
Soit une image de n × n pixels noirs ou blancs.
On suppose que cette image contient un rectangle monochromatique de l × h pixels, dont le coin
inférieur gauche est situé au pixel de coordonnées (x, y).
On choisit de ne profiter que de ce rectangle pour compresser l’image. On représentera donc l’image
compressée en deux « temps » :
— d’abord, les caractéristiques du rectangle monochromatique ;
— puis la suite des pixels n’appartenant pas à ce rectangle, représentés comme d’habitude dans les
images noir et blanc.
Question 2.1 On supposera dans cette partie que les entiers n, l, h, x et y sont représentés sur 2 octets.
Justifier ce choix.
2
Question 2.2 Combien de bits sont nécessaires pour caractériser un rectangle monochromatique ?
En déduire un critère pour savoir s’il est « rentable » de compresser l’image par cette méthode, en
fonction des différentes tailles concernées.
Question 2.3 Que faut-il ajuster si on souhaite utiliser cette méthode de compression sur des images
en niveaux de gris ou en couleurs ?
Donner des exemples d’images sur lesquelles la compression sera efficace, et des exemples sur lesquelles elle ne permettra pas de réduire la taille de l’image.
2.2
Recherche unidimensionnelle
Dans cette partie, nous allons étudier le problème de reconnaissance de forme sur des tableaux
unidimensionnels (implémentés par des listes Python en l’occurrence). Nous supposerons donnés un
entier n et un tableau tab de taille n dont les cases contiennent 0 ou 1. Nous supposerons que les indices
du tableau sont compris entre 0 et n-1. Le but de cette partie est de trouver le nombre maximal de 0
contigüs (c’est à dire figurant dans des cases consécutives) dans le tableau.
Dans cette partie nous utiliserons le tableau suivant comme exemple :
i
0 1 2 3 4 5 6 7 8 9 10 11 12
tab[i] 0 0 1 1 0 0 0 1 0 0
0
1
1
Question 2.4 Écrire une fonction nombreZerosDroite(i, tab) prenant en paramètres le tableau tab
de taille n ainsi qu’un indice i compris entre 0 et n-1. Cette fonction devra renvoyer le nombre de cases
contigües du tableau contenant 0 à droite de la case d’indice i, cette case étant comprise.
D’un point de vue formel il s’agit de renvoyer 0 si la case d’indice i contient un 1 et sinon de renvoyer
max{j − i + 1 tel que i 6 j < n et ∀k ∈ [i, j], tab[k] = 0}
Sur le tableau exemple précédent, en prenant comme indice i = 3 nous obtenons 0 et pour l’indice i = 5
votre fonction devra renvoyer 2. Notez que si la case i contient 1, alors votre fonction devra renvoyer 0.
Il est maintenant possible de réaliser un algorithme de complexité optimale utilisant la fonction
précédente. En voici une brève description. Parcourons le tableau de gauche à droite et à chaque début
de plage de 0 contigüs, nous calculons la taille de cette plage puis repartons juste après elle. Ayant
ainsi calculé la taille de toutes les plages de 0 il suffit de retenir celle de taille maximale. Sur l’exemple
précédent, on part de l’indice 0 qui est un début de plage de 0 de taille 2. Nous continuons donc à
chercher le prochain début de plage à partir de l’indice 0 + 2 = 2. On examine ensuite l’indice 3 qui
contient encore un 1 puis arrivons à l’indice 4 qui est le début d’une plage de 0 de taille 3. Nous allons
donc chercher le prochaine début de plage à partir de l’indice 4 + 3 = 7 etc.
Question 2.5 Écrire une fonction nombreZerosMaximum(tab) qui renvoie le nombre maximal de 0
contigüs en utilisant l’algorithme précédent. On attachera une attention particulière à ce que l’algorithme
produit soit de complexité linéaire c’est à dire en temps O(n).
2.3
De la 1D vers la 2D
Cette partie consiste à développer un algorithme efficace pour détecter un rectangle d’aire maximale
rempli de 0 dans un tableau bidimensionnel. Par mesure de simplification, nous travaillerons sur des
tableaux carrés et nous supposerons donné un tableau tab2 de taille n × n. Un tableau bidimensionnel
sera adressé par tab2[i][j] et i représentera le numéro de ligne dans nos exemples.
Nous utiliserons le tableau suivant comme exemple :
3
i\j
0
1
2
3
4
5
6
7
0
0
0
1
0
0
0
0
0
1
0
0
0
1
0
0
1
0
2
1
0
0
0
1
1
1
1
3
1
0
0
0
1
0
1
1
4
0
1
0
0
0
0
0
0
5
0
0
0
0
0
0
1
0
6
0
0
0
0
0
0
0
0
7
1
1
1
1
1
1
1
1
Méthode naïve La première méthode proposée consiste à prendre une cellule (i, j) et à trouver
un rectangle d’aire maximale dont le coin inférieur gauche est cette cellule. Remarquez que suivant
l’orientation donnée dans le tableau exemple ci-dessus, un rectangle d’aire maximale de coin inférieur
gauche la cellule (i, j) aura comme coin supérieur droit la cellule (i’, j’) avec i’ 6 i et j’ > j. Par
exemple, un rectangle d’aire maximale de coin inférieur gauche la cellule (i, j) = (3, 2) aura comme coin
supérieur droit la cellule de coordonnées (2, 6).
Question 2.6 Écrire une fonction rectangleHautDroit(tab2, i, j) qui renvoie l’aire d’un rectangle
d’aire maximale rempli de 0 et de coin inférieur gauche (i, j). On cherchera la solution la plus efficace
possible. Pour i = 3 et j = 2 sur le tableau exemple ci-dessus, la fonction devra renvoyer la valeur 10.
Question 2.7 Expliquer comment trouver naïvement un rectangle d’aire maximale rempli de 0 en utilisant la fonction rectangleHautDroit. Quelle serait la complexité de cette approche en fonction de
n?
Un peu de précalcul Notre algorithme parcourt de nombreuses fois les même cases afin de vérifier la
présence d’un 0 ou d’un 1. Nous allons donc effectuer avant notre algorithme un précalcul de certaines
valeurs ce qui nous permettra, dans la partie 2.4, d’accélérer les fonctions précédentes.
Pour chaque cellule (i, j), nous allons calculer le nombre ci,j de cellules contigües contenant 0 au
dessus de la cellule (i, j), cette dernière étant comprise. Ce nombre est tel que les cellules (i, j), (i −
1, j), . . . , (i − ci,j + 1, j) contiennent 0 et la cellule (i − ci,j , j) contient 1 ou bien cette cellule n’existe
pas. Ces valeurs ci,j seront rangées dans un tableau col. Le tableau col suivant est obtenu à partir du
tableau exemple.
i\j
0
1
2
3
4
5
6
7
0
1
2
0
1
2
3
4
5
1
1
2
3
0
1
2
0
1
2
0
1
2
3
0
0
0
0
3
0
1
2
3
0
1
0
0
4
1
0
1
2
3
4
5
6
5
1
2
3
4
5
6
0
1
6
1
2
3
4
5
6
7
8
7
0
0
0
0
0
0
0
0
Question 2.8 Écrire une fonction colonneZeros(tab2) qui renvoie un tableau bidimensionnel d’entiers
col de taille n × n et tel que col[i][j] donne le nombre de cellules contigües contenant 0 au dessus de
(i, j), cette cellule étant comprise. On apportera un soin particulier à programmer la fonction la plus
rapide possible.
Question 2.9 Quelle est la complexité de la fonction colonneZeros ?
4
2.4
Algorithme optimisé
Rectangle d’aire maximale dans un histogramme Une nouvelle étape dans notre algorithme
réside dans la résolution du problème du calcul d’un rectangle d’aire maximale inscrit dans un histogramme. Nous supposerons donné un histogramme c’est à dire un tableau histo de taille n contenant
des entiers. Chaque valeur représentera la hauteur d’une barre de l’histogramme. Par exemple le tableau
suivant est associé à l’histogramme à sa droite.
i
histo[i]
0
3
1
1
2
2
3
4
4
2
5
2
6
0
7
1
L’idée est de calculer un indice L[i] pour chaque colonne i, tel que L[i] est le plus petit entier j
satisfaisant : 0 6 j 6 i et histo[k] > histo[i], pour tout k tel que j 6 k 6 i.
Notons que 0 6 L[i] 6 i. Dans notre exemple nous aurons L[2] = 2 car la colonne 1 est strictement
plus petite que la colonne 2. Nous aurons par ailleurs L[5] = 2 car les trois valeurs histo[2], histo[3]
et histo[4] sont toutes > histo[5] mais histo[1] < histo[5].
Nous pourrions calculer les valeurs L[i] de manière naïve mais cela ne permettrait pas d’améliorer
notre algorithme. Nous allons donc procéder autrement.
On calcule successivement les valeurs de L[i] pour i = 0 . . . n − 1. Pour calculer L[i] on pose j =
i et on fait décroître j tant que les colonnes sont plus grandes de la manière suivante :
Répéter :
— Si j = 0 alors affecter L[i] = 0 et terminer.
— Sinon :
— Si histo[j - 1] < histo[i] alors affecter L[i] = j et terminer.
— Sinon histo[j - 1] > histo[i] alors affecter j = L[j - 1] et continuer.
Question 2.10 Montrer que l’algorithme précédent calcule correctement les valeurs de L. De plus, montrer que l’algorithme fonctionne un temps proportionnel à n sur le cas particulier du tableau
histo = [1, 2, 3, ... , n - 1, n, n, n - 1, ... , 1] de taille 2n.
On supposera donnée une fonction calculeL(histo) qui renvoie en temps O(n) le tableau L de taille
n tel que L[i] est l’indice défini précédemment. On supposera aussi donnée une fonction équivalente
calculeR(histo) qui renvoie en temps O(n) un tableau R dont les valeurs R[i] > i qui de manière
analogue est l’indice maximal tel que histo[k] > histo[i] pour tout k tel que i 6 k 6 R[i].
Question 2.11 Justifier que pour tout i, le rectangle commençant à l’indice L[i], terminant à l’indice
R[i] et de hauteur histo[i] est inclus dans l’histogramme.
Question 2.12 Soit un rectangle d’aire maximale inscrit dans l’histogramme. Supposons que ce rectangle
commence à l’indice l, termine à l’indice r, et a pour hauteur h. Montrer qu’il existe i ∈ [l . . . r] tel que
histo[i] = h, L[i] = l, et R[i] = r.
Question 2.13 En déduire une fonction plusGrandRectangleHistogramme(histo) qui calcule et renvoie l’aire d’un plus grand rectangle inscrit dans l’histogramme. Donner la complexité de votre fonction
plusGrandRectangleHistogramme.
2.5
Conclusion
En revenant au problème initial du calcul d’un rectangle de 0 d’aire maximale dans une matrice en
deux dimensions, remarquer que chaque ligne du tableau col calculé par la fonction colonneZeros de la
question 2.8 peut être interprétée comme un histogramme.
En utilisant cette analogie, il est possible de proposer une méthode efficace de résolution du problème.
Question 2.14 Écrire la fonction rectangleToutZero(tab2) qui calcule un rectangle d’aire maximale
rempli de 0 dans le tableau tab2 et renvoie son aire.
Question 2.15 Quelle est la complexité de votre fonction ?
5
Langage Python
Listes
>>> maListe = [1 ,8 , ’e ’]
>>> [42 for i in range (7)]
[42 , 42 , 42 , 42 , 42 , 42 , 42]
>>> maListe [0]
1
>>> maListe [1]
8
>>> maListe [ -1]
’e ’
>>> len ( maListe )
3
>>> maListe . append (12)
>>> maListe
[1 , 8 , ’e ’ , 12]
>>> maListe . remove (8)
>>> maListe
[1 , ’e ’ , 12]
>>> maListe . pop (1)
’e ’
>>> maListe
[1 , 12]
>>> maListe . insert (1 , ’a ’)
>>> maListe
[1 , ’a ’ , 12]
# d é finition d ’ une liste
# d é finition d ’ une liste de 7 é l é ments identiques
# le premier é l é ment d ’ une liste a l ’ indice 0
# le dernier é l é ment de la liste
# longueur d ’ une liste
# ajout d ’ un é l é ment en fin de liste
# suppression du premier é l é ment é gal à 8
# renvoie l ’é l é ment d ’ indice 1
# et le supprime de la liste
# ins è re l ’é l é ment ’a ’ à l ’ indice 1 du tableau
Tableaux bidimensionnels
>>> monTab = [[1 ,8 , ’e ’] , [] , [42 ,14]] # d é finition d ’ un tableau de tableaux
>>> monTab [0]
# la premi è re coordonn é e d é signe une ligne
[1 ,8 , ’e ’]
>>> monTab [2][1]
# avec deux coordonn é es on r é cup è re un é l é ment
14
>>> [ len ( l ) for l in monTab ]
# attention chaque ligne peut etre
[3 ,0 ,2]
# de longueur diff é rente
>>> [[0 for j in range (4)] for i in range (3)]
[[0 ,0 ,0 ,0] ,
# d é finition d ’ un tableau rectangulaire
[0 ,0 ,0 ,0] ,
# attention à l ’ ordre des indices i et j
[0 ,0 ,0 ,0]]
>>> len ( monTab )
# nombre de lignes
3
Sources
Ces deux problèmes sont inspirés de sujets de concours respectivement de l’École Normale Supérieure
de Lyon et du concours commun Polytechnique - ÉNS Cachan - ESPCI.
6
Téléchargement