Vous êtes sur la page 1sur 12

MINISTÈRE DE L’ÉDUCATION NATIONALE

DE LA FORMATION PROFESSIONNELLE,
DE L’ENSEIGNEMENT SUPÉRIEUR
ET DE LA RECHERCHE SCIENTIFIQUE

Cycle de Préparation de l’Agrégation en Informatique

CONCOURS D’ADMISSION SEPTEMBRE 2021

ÉPREUVE : INFORMATIQUE FONDAMENTALE ET PROGRAMMATION

Durée : 4 heures Coefficient : 4

Nom et Prénom :

Numéro d’examen :

Centre d’examen :

Le sujet comporte 12 pages au format A4


(La page de garde est incluse)
Page 2

CONSIGNES :
— Le sujet comporte trois problèmes indépendants.
— Tous les programmes demandés doivent être écrits en Python
— La seule fonction prédéfinie en Python qui est permise est len considérée de complexité constante
(O(1))
— Aucun document n’est permis, aucun instrument de calcul n’est autorisé.
— Conformément au règlement du concours, l’usage d’appareils communicants ou connectés est stric-
tement interdit durant l’épreuve.
— Les candidats sont invités à soigner la présentation de leur copie, à mettre en évidence les principaux
résultats, à respecter les notations de l’énoncé et à donner des démonstrations complètes - mais
brèves - de leurs affirmations.
— Si, au cours de l’épreuve, un candidat repère ce qui lui semble être une erreur d’énoncé, il le signalera
sur sa copie et poursuivra sa composition en expliquant les raisons des initiatives qu’il est amené à
prendre.
— Pour le troisième problème, les candidats sont appelés à marquer leurs réponses sur la feuille du
sujet uniquement, sinon aucune réponse ne sera acceptée
Page 3

Problème I : Sous-séquence commune

Ayoub pense que Najib est son frère perdu depuis longtemps. Mais Najib pense que Ayoub a tort, et
pour le prouver, il a obtenu des échantillons d’ADN de lui-même et de Ayoub. Maintenant, Najib vous a
donné les échantillons d’ADN et c’est à vous de dire s’ils sont frères ou non.

Les échantillons d’ADN de Ayoub et Najib sont des chaînes de caractères SA et SN , tous deux ont
la même longueur n, et se composent uniquement des caractères «A», «T», «G» et «C». S’il existe une
sous-séquence commune de SA et SN qui a une longueur supérieure ou égale à 0, 99 × n, alors Ayoub et
Najib sont frères, dans les autres cas, ils ne le sont pas.

Une sous-séquence d’une chaîne X est toute chaîne que vous pouvez obtenir en supprimant n’importe
quel nombre de caractères de X.(par Exemple : la chaîne "AGC" est une sous-séquence de la chaîne
"TAATGGC")

On définira l’ensemble E = {0 A0 ,0 T 0 ,0 G0 ,0 C 0 }

Soit une séquence S, on notera Si l’élément d’indice i dans S et P r(S, i) séquence S privée du caractère
Si , (par Exemple si S = ”AGT C”, alors S1 = ”G” et P r(S, 1) = ”AT C”).

On notera |S| la taille de la séquence S, et |S|c désignera le nombre d’occurrence de l’élément c dans
S. (Par exemple, pour S= ”AAGT AC”, on a |S|A = 3 et |S| = 6).

Question 1: Écrire une fonction Est_Valide(sequence), qui prend comme paramètre une séquence et
retourne vrai si et seulement la séquence ne contient que des lettres de l’ensemble E. Donner sa complexité.
Exemple :
• Est_Valide(’AAGTCTA’) → True
• Est_Valide(’ATTTEC’) → False

Avant de calculer la longueur de la plus longue sous-séquence commune, on souhaite faire une vérifica-
tion qui peut nous faire gagner du temps, en exploitant l’implication suivante :

Si le nombre de lettres communes entre la séquence SA et SN est à inférieur à 0, 99 × n , alors Najib et


Ayoub ne sont pas frères.

Question 2: Écrire une fonction chaîne_to_liste(sequence), qui prend comme paramètre une sé-
quence et retourne une liste composée des lettres de cette chaîne.
Exemple :
• chaîne_to_liste("AGTTCC") → [’A’, ’G’, ’T’, ’T’, ’C’, ’C’].
Page 4

Question 3: Écrire une fonction Trier(sequence), qui prend comme paramètre une séquence sous
forme de liste et la trie en ordre croissant.
Exemple :
• Trier([’A’, ’G’, ’T’, ’A’, ’C’, ’T’, ’C’, ’A’]) → [’A’, ’A’, ’A’, ’C’, ’C’, ’G’, ’T’, ’T’].

Question 4: En utilisant les fonctions chaîne_to_liste et Trier, écrire une fonction


nbr_lettres_communes(SA,SN), qui prend comme paramètre deux séquences SA et SN , et calcule
le nombre de lettres communes entre SA et SN . (Il sera préférable que la complexité de cette de fonction
soit égale à la complexité de la fonction Trier).
Exemple :
• nbr_lettres_communes("AGTTCCAATGGGCA" , "TCCAACAATGTGCTA") → 12.

On souhaite optimiser le calcul des lettres communes des deux séquences.

Question 5:
Écrire une fonction occurence_bases_puriques(sequence), qui prend comme paramètre une sé-
quence et retourne un dictionnaire dont les clés sont les éléments de E et la valeur de chaque clé est le
nombre de son occurrence dans la séquence. Donner sa complexité.
Exemple :
• occurence_bases_puriques(’AGAGAATGTC’) → {’A’ : 4, ’T’ : 2, ’G’ : 3, ’C’ : 1}.

Question 6: En déduire une fonction nbr_lettres_communes2(SA, SN ) qui calcule le nombre de


lettres communes entre les séquences SA et SN , comme suit : Σ min(|SA|c , |SN |c ). Donner sa complexité.
c∈E

Question 7: En déduire une fonction peut_être_frères(SA,SN), qui prend en paramètres les


séquences SA et SN , et retourne vrai si et seulement si le nombre de lettres communes entre la séquence
SA et SN est supérieur ou égal à 0, 99 × n

Maintenant, on va essayer de calculer la longueur de la plus longue sous-séquence commune (PLSC)


de trois méthodes différentes.

Question 8: Ecrire une fonction PLSC1(SA,SN) qui prend en paramètres deux séquences SA et SN
de taille n et retourne la taille de la PLSC selon le principe suivant :





0 si |SA| = 0 ou |SN | = 0

P LSC(SA, SN ) =  n sinon si SA = SN



 max P LSC(P r(SA, i), P r(SN, j)) sinon
0≤i,j≤n−1

En déduire sa complexité.
Page 5

Question 9: Ecrire une fonction PLSC2(SA,SN) qui prend en paramètres deux séquences SA et SN
de taille n et retourne la taille de la PLSC selon le principe suivant :



 0 si |SA| = 0 ou |SN | = 0

P LSC(SA, SN ) = 1 + P LSC(P r(SA, n − 1), P r(SN, n − 1)) sinon si SAn−1 = SNn−1


 max(P LSC(SA, P r(SN, n − 1)), P LSC(P r(SA, n − 1), SN ))

sinon

Malgré ce changement, la complexité est encore élevée car il y a des calculs qui se répètent alors qu’on
peut les éviter. Par exemple, si on prend l’arbre partiel récursif de l’appel PLSC2 sur les deux séquences
"ACGT" et "AGGC" :

le calcul PLSC2("ACG","AGG") sera fait deux fois, ainsi si on dessine l’arbre complet, on constatera
qu’il y a plusieurs calculs qui se répètent plusieurs fois.

Question 10: Pour éviter ces calculs redondants ,écrire une fonction PLSC3(SA,SN) qui prend en
paramètres deux séquences SA et SN de taille n et retourne la taille de la PLSC selon le principe suivant :
• On crée une matrice carrée T d’ordre n+1 initialisé par des 0
• ∀1 ≤ i, j ≤ n, si SAi = SNj alors Ti,j = 1 + Ti−1,j−1 , sinon Ti,j = max(Ti,j−1 , Ti−1,j )
• retourner Tn,n

Question 11: En déduire une fonction Sont_frères(SA,SN) qui prend en paramètres deux séquences
SA et SN et retourne vrai si et seulement les personnes ,dont les séquences d’ADN sont SA et SN , sont
frères.
Page 6

Problème II : Échangeurs de Polynômes

Dans ce problème on s’intéresse à des polynômes à coefficients réels qui s’annulent en 0. Un tel polynôme
P s’écrit donc P (x) = a1 x + a2 x2 + ... + am xm . Le but de ce problème est d’étudier la position relative
autour de l’origine de plusieurs polynômes de ce type.

Dans tout le problème, les polynômes sont représentés par des listes de nombres flottants de la forme
[a1 , a2 , ..., am ]. Le nombre am peut être nul, par conséquent un polynôme donné admet plusieurs représen-
tations sous forme de tableau.

Le problème est découpé en deux parties qui peuvent être traitées de manière indépendante. Cependant,
la partie II utilise les notions et notations introduites dans la partie I.

Partie I : Permutation de n polynômes

Question 12: Afin de se familiariser avec cette représentation, écrire une fonction evaluation qui
prend en arguments un polynôme P , représenté par une liste, et un nombre flottant v, et qui renvoie la
valeur de P (v).

Nous commençons notre étude par quelques observations. Voici des exemples de graphes de polynômes
autour de l’axe des abscisses.

On remarque que le comportement au voisinage de l’origine est décrit par le premier monôme ak xk dont
le coefficient ak est non nul (les coefficients a1 , ..., ak−1 étant donc tous nuls). En effet, quand x est petit,
le terme ak+1 xk+1 + ... + am xm est négligeable devant le terme ak xk . Cet entier k est la valuation du
Page 7

polynôme à l’origine. Par exemple, la valuation du polynôme −2x3 − 3x5 + 4x7 est 3. On remarque alors
les deux règles suivantes au voisinage de l’origine :
— Si la valuation k est paire, le graphe du polynôme reste du même côté de l’axe des abscisses.
— Si la valuation k est impaire, le graphe du polynôme traverse l’axe des abscisses.

Question 13: Écrire une fonction valuation qui prend en argument un polynôme P et renvoie sa
valuation. Par définition, cette fonction renverra 0 si P est le polynôme nul.

On s’intéresse maintenant aux positions relatives autour de l’origine des graphes de deux polynômes P 1
et P 2 . La figure suivante montre les graphes de polynômes autour de l’origine.

On remarque que le comportement de ces graphes dépend de la parité de la valuation de la différence


P 1 − P2 :
— Si la valuation de P1 −P2 est paire, les deux graphes se touchent mais ne se traversent pas à l’origine.
— Si la valuation de P1 − P2 est impaire, les deux graphes se traversent à l’origine.

Question 14: Écrire une fonction dif f erence qui prend en arguments deux polynômes P1 et P2 (dont
les tailles peuvent être différentes) et qui renvoie la différence des polynômes P1 − P2 .

Question 15: Écrire une fonction compare_neg qui prend en arguments deux polynômes P1 et P2 et
qui renvoie :
— un entier strictement négatif si P1 (x) est plus petit que P2 (x), pour x négatif assez petit
— 0 si les deux polynômes P1 et P2 sont égaux
— un entier strictement positif si P1 (x) est plus grand que P2 (x), pour x négatif assez petit.

On admettra sans démonstration que la fonction compare_neg définit une relation d’ordre.
Page 8

Enfin, passons à l’étude des graphes de trois polynômes. Les figures ci-après montrent les positions
relatives de trois polynômes P1 , P2 et P3 autour de l’origine, avec la légende suivante :
P1 —– P2 − − − P3 ....

Le choix de ces polynômes est fait pour qu’à chaque fois les inégalités P1 (x) > P2 (x) > P3 (x) soient vérifiées
pour x légèrement négatif. Maintenant, observons les positions relatives de ces graphes pour x légèrement
positif. On remarque que l’ordre des courbes est permuté : on passe de l’ordre P1 (x) > P2 (x) > P3 (x) à un
autre ordre. La donnée des trois polynômes P1 , P2 et P3 définit donc une unique permutation π de {1, 2, 3}
telle que Pπ(1) (x) > Pπ(2) (x) > Pπ(3) (x), pour x positif et assez petit. On note que les six permutations de
{1, 2, 3} sont possibles, comme le montrent les six exemples ci-dessus.
De manière générale, on dit qu’une permutation π de {1, 2, ..., n} permute les polynômes P1 , P2 , ..., Pn
si et seulement si :

P1 (x) > P2 (x) > ... > Pn (x) pour x negatif assez petit

et Pπ(1) (x) > Pπ(2) (x) > ... > Pπ(n) (x) pour x positif assez petit

Ce qui est vrai pour trois polynômes ne l’est plus à partir de quatre polynômes : il existe des permutations
qui ne permutent aucun ensemble de polynômes P1 , P2 , ..., Pn .
Page 9

Dans la suite, les permutations de {1, 2, ..., n} seront représentées par des listes d’entiers de taille n,
indexés à partir de 1 et contenant tous les entiers entre 1 et n.

Question 16: Écrire une fonction tri qui prend en argument une liste t contenant n polynômes et
qui la trie en utilisant la fonction compare_neg, de telle sorte que l’on ait t[1](x) > t[2](x) > ... > t[n](x)
pour x négatif et assez petit. Le candidat ne pourra pas utiliser pour cette question de fonction de tri
prédéfinie.

Question 17: Écrire une fonction verif ier_permute qui prend en arguments une permutation π de
{1, 2, ..., n} et une liste t de même taille supposée triée par la fonction tri, et renvoie vrai si π permute les n
polynômes t[1], t[2], ..., t[n] contenus dans t, et faux sinon. On pourra s’aider d’une fonction compare_pos,
similaire à la fonction compare_neg, pour comparer deux polynômes pour x positif assez petit.

Partie II : Échangeurs de n polynômes

Dans la suite, nous dirons qu’une permutation π de {1, 2, ..., n} est un échangeur s’il existe n polynômes
P1 , P2 , ..., Pn telle que π permute ces polynômes. Nous allons maintenant écrire des fonctions qui répondent
aux questions suivantes : Une permutation π est-elle un échangeur ? Peut-on dénombrer les échangeurs ?
Peut-on énumérer les échangeurs ?

Une condition nécessaire et suffisante pour qu’une permutation soit un échangeur est la suivante : une
permutation π de {1, 2, ..., n} est un échangeur si et seulement s’il n’existe aucun entiers a, b, c, d tels que
n ≥ a > b > c > d ≥ 1 et

π(b) > π(d) > π(a) > π(c) ou π(c) > π(a) > π(d) > π(b) (1)

Question 18: Écrire une fonction est_echangeur_aux qui prend en argument une permutation π de
{1, 2, ..., n} et un entier d tel que 1 ≤ d ≤ n et qui renvoie vrai s’il n’existe aucun entier a, b et c tels que
n ≥ a > b > c > d et vérifiant (1), et f aux sinon.

Question 19: En utilisant la fonction est_echangeur_aux, écrire une fonction est_echangeur qui
prend en argument une permutation π de {1, 2, ..., n} et renvoie vrai si π est un échangeur, et f aux sinon.
Page 10

On admet sans démonstration que la relation de récurrence suivante permet de compter le nombre a(n)
de permutations de {1, 2, ..., n} qui sont des échangeurs :

n−1
X
a(1) = 1, a(n) = a(n − 1) + a(i) × a(n − i)
i=1

Question 20: Écrire une fonction nombre_echangeurs qui prend un entier n en argument et renvoie
le nombre d’échangeurs a(n).

Enfin, les deux questions suivantes ont pour but d’énumérer tous les échangeurs de {1, 2, ..., n}.

Question 21: Écrire une fonction decaler qui prend en arguments une liste t de taille n et un entier
v, et renvoie une nouvelle liste u de taille n + 1 telle que :



 u[1] = v


u[i] = t[i − 1] si t[i − 1] < v et 2 ≤ i ≤ n + 1

u[i] = 1 + t[i − 1] si t[i − 1] ≥ v et 2 ≤ i ≤ n + 1

L’algorithme que nous allons utiliser pour énumérer les échangeurs de {1, 2, ..., n} consiste à énumérer
successivement les échangeurs de {1, 2, ..., k}, pour tout k de 1 à n, dans un tableau t de taille a(n). Si
on suppose qu’un tableau t contient les m échangeurs de {1, ..., k} entre les cases t[1] et t[m], on peut en
déduire les échangeurs de {1, ..., k + 1} de la manière suivante : pour tout entier v entre 1 et k + 1 et tout
entier i entre 1 et m, on décale (à l’aide de la fonction decaler) l’échangeur t[i] avec v puis on teste si le
résultat est un échangeur (avec la fonction est_echangeur_aux).

Question 22: Écrire une fonction enumerer_echangeurs qui prend un entier n en argument et
renvoie une liste contenant les a(n) échangeurs de {1, 2, ..., n}. On pourra utiliser une seconde liste pour
stocker temporairement les nouveaux échangeurs.
Page 11

Problème III : A propos des arbres

On rappelle quelques définitions :

un arbre binaire est une structure de données qui peut se représenter sous la forme d’une hiérarchie
dont chaque élément est appelé nœud, le nœud initial étant appelé racine. Dans un arbre binaire, chaque
élément possède au plus deux éléments fils au niveau inférieur, habituellement appelés gauche et droit.

Un arbre binaire de recherche (ABR) est un arbre binaire dans lequel chaque nœud possède une clé,
telle que chaque nœud du sous-arbre gauche ait une clé inférieure ou égale à celle du nœud considéré, et
que chaque nœud du sous-arbre droit possède une clé supérieure ou égale à celle-ci.

Question 23: Dessinez tous les ABRs dont les éléments sont : 5,8,12,21

Question 24: Quel est la complexité au pire des cas d’une recherche optimale dans un ABR à n
noeuds ? (Cochez la bonne réponse)
O(logn)
O(nlogn)
O(n2 )
Page 12

Question 25: Quel est la complexité au pire des cas d’une recherche optimale dans un ABR à nn
noeuds ? (Cochez la bonne réponse)
O(logn)
O(nlogn)
O(nn )

Question 26: Dessinez l’ABR dont le parcours préfixe est : 8,3,1,6,4,7,10,14,13

FIN
Bonne chance

Vous aimerez peut-être aussi