• Aucun résultat trouvé

sur un alphabet de s lettres ?

N/A
N/A
Protected

Academic year: 2022

Partager "sur un alphabet de s lettres ?"

Copied!
7
0
0

Texte intégral

(1)

I. Sous-mots

On considère un ensemble fini Σ de cardinal s que l’on appelle alphabet. Cet alphabet peut être l’alphabet latin habituel à 26 lettres, mais dans certaines ques- tions on considèrera un alphabet à deux lettres seulement.

Pour tout entier naturel non nul p, une fonction de {1, 2, · · · , p} à valeur dans Σ est appelée un mot de p lettres (ou de longueur p) sur Σ. En procédant de gauche à droite, on dira que x(1) est la première lettre du mot x, que x(2) est la deuxième lettre et ainsi de suite.

Par convention, il existe un seul mot de longueur 0 appelé mot vide et noté . 1. Soit p un naturel non nul, quel est le nombre de mots de moins de p lettres

sur un alphabet de s lettres ?

2. Dans cette question on prend pour Σ l’alphabet latin de 26 lettres. Un mot de p lettres sur cet alphabet est représenté informatiquement par une liste de p caractères.

Le tableau suivant définit deux telles listes et les désigne par des variables x et y. Les longueurs sont désignées par m et n. Dans toute cette question ces variables désigneront toujours ces objets.

mot longueur liste

bonbon m:=6 x:=[b,o,n,b,o,n]

quelbonbonbon n:=13 y:=[q,u,e,l,b,o,n,b,o,n,b,o,n]

a. Dans la figure 1, le symbole <> signifie 6=. Au moment de l’étape debut, les variables i et j désignent toutes les deux l’entier 1. Que désignent- elles au moment de l’étape fin ?

b. Que désignent les variables i et j au moment de l’étape fin du dia- gramme de la figure 2.

3. Implémenter en syntaxe Maple, l’algorithme présenté dans la figure 2. Il est inutile de définir une procédure.

4. Soit m n deux entiers naturels non nuls. On dira qu’un mot x de m lettres est un sous-mot d’un mot y de n lettres si et seulement si il existe une application ϕ telle que :

ϕ strictement croissante de {1, 2, · · · , m} dans {1, 2, · · · , n}

x = y ϕ

(on rappelle que selon la définition du début, un mot est une fonction)

Fig. 1 – Une boucle

a. Montrer que « bonbon » est un sous-mot de « quelbonbonbon ». On précisera toutes les fonctions ϕ vérifiant les propriétés caractérisant la définition d’un sous-mot,

b. Définir, en syntaxe Maple, une procédure est_sous_mot telle que : – x désignant une liste de m caractères associée à un mot x, – y désignant une liste de n caractères associée à un mot y,

– l’appel est_sous_mot(x,m,y,n) renvoie 1 si x est un sous-mot de y et renvoie 0 sinon.

5. Lorsque x et y sont deux mots sur Σ de longueurs respectives m et n, on désigne par M (x, y) l’ensemble des applications ϕ vérifiant les conditions de la question 4. On note alors µ(x, y) le nombre d’éléments de M (x, y).

En particulier M (x, y) est non vide et µ(x, y) 6= 0 si et seulement si m n et x est un sous-mot de y.

a. Lorsque x et y sont des mots de longueur supérieure ou égale à 2, on note x

1

et y

1

les premières lettres de x et de y et on définit des mots x

0

et y

0

en supprimant la première lettre.

Par exemple

x = bonbon y = quelbonbonbon

)

( x

1

= b x

0

= onbon

y

1

= q y

0

= uelbonbonbon

(2)

Fig. 2 – Un algorithme

Lorsque x

1

= y

1

, montrer que µ(x, y) = µ(x

0

, y

0

) + µ(x, y

0

).

Lorsque x

1

6= y

1

, montrer que µ(x, y) = µ(x, y

0

).

b. Proposer un algorithme récursif qui prend en entrée des listes x, y, des longueurs m, n et qui renvoie la valeur de µ(x, y).

II. Tirage sans remise

Soient p et n deux entiers naturels non nuls avec p n.

On veut former un algorithme permettant de tirer aléatoirement et successivement p nombres distincts au hasard entre 1 et n et les placer dans un tableau. Cela revient

à tirer sans remise p boules dans une urne contenant n boules numérotées ou encore à former aléatoirement une application injective de {1, · · · , p} dans {1, · · · , n}.

Les variables p, n (constantes) désignent les nombres p et n.

Lorsque k désigne un entier k entre 1 et p, l’appel de la procédure random(1..k)()

renvoie un nombre entier aléatoire entre 1 et k.

L’algorithme qui vous est demandé doit vérifier certaines contraintes.

– Vous ne devez appeler la procédure random que p fois.

– Vous devez utiliser un tableau auxiliaire B indexé de 1 à n. Le début de ce tableau contenant les nombres qui n’ont pas encore été tirés.

– Vous devez renvoyer un tableau indexé de 1 à p.

1. Présenter l’algorithme dans un schéma.

2. Implémenter l’algorithme dans une procédure tirage de paramètres p, n.

III. Tri rapide

Tri "rapide".

On commence par partitionner le tableau en deux parties en permutant certains éléments de telle sorte que toutes les valeurs de la partie gauche du tableau soient inférieures aux valeurs de la partie droite.

Pour obtenir un tel partionnement, on utilise une valeur x du tableau. À gauche se trouvent des valeurs toutes inférieures ou égales à x, à droite toutes les valeurs doivent être plus grandes que x (mais pas forcément strictement plus grandes).

Ensuite la procédure s’appelle récursivement sur chaque partie du tableau.

Former les diagrammes conventionnels puis rédiger des procédures partitionner(p,q) et tri_rap(p,q)

implémentant ce processus.

Les procédures utilisent la variable globale A comme nom du tableau.

L’appel de la procédure partitionner(p,q,x) affecte A[p] à une variable locale x et renvoie un entier i entre p et q-1 après avoir permuté des valeurs de A pour que

q k i A[k] x

i + 1 k q x A[k]

(3)

IV. Corrigé du devoir sur les sous-mots

1. Il est important de remarquer qu’un mot n’est pas un ensemble de lettres, l’ordre compte. Un mot est représenté par une fonction. Compter les mots de différentes tailles, c’est donc dénombrer des fonctions dont le dommaine de définition varie. On classe ces fonctions suivant le nombre de lettres en partant de 0 avec le seul mot vide. Comme le nombre de fonctions d’un ensemble à k éléments dans un ensemble à s éléments est s

k

( voir un cours de dénombrement), le nombre de mots de moins de p lettres est :

1 + s + s

2

+ · · · + s

p

= s

p+1

1 s 1

2. a. La figure 1 représente une boucle dans laquelle les variables i et j re- présentent des compteurs de lettres respectivement dans le premier mot x et dans le deuxième mot y.

La variable i n’est assignée nulle part dans cette boucle, elle désigne donc toujours 1 à la fin.

En revanche, la boucle incrémente j jusqu’à trouver une lettre d’indice j égale à la première lettre de x. C’est à dire la cinquème lettre b de y dans le cas particulier considéré. À la fin, la variable j désigne donc 5.

b. La figure 2 incorpore la boucle précédente dans une autre qui incrémente le compteur i de x tant que l’extrémité de l’un des mots n’est pas dépassée.

On parcourt donc le premier bonbon de quelbonbonbon et on finit avec i en dehors de x et j pointant vers le deuxième n de y.

En conclusion, à la fin, i désigne 7 et j désigne 10.

3. En syntaxe Maple, l’algorithme de la 2 se code de la manière suivante :

#pour pouvoir tester

x := [’b’,’o’,’n’,’b’,’o’,’n’];

y := [’q’,’u’,’e’,’l’,’b’,’o’,’n’,’b’,’o’,’n’,’b’,’o’,’n’];

m := 6;

n := 13;

i :=1; j:=i;

while i<=m and j<=n do

while i<=m and x[i]<>y[j] do j:=j+1;

od;

i:=i+1;

od:

print(i,j);

Les quatre premières et la dernière des lignes ne sont pas formellement de- mandées par l’énoncé, mais elles sont indispensables si on veut exécuter le code pour le tester.

4. a. Il est bien évident que bonbon est un sous-mot de quelbonbonbon. Pour le montrer, il suffirait de trouver une injection strictement croissante.

En fait, on les forme toutes. Il est commode de visualiser le numéro des lettres dans des tableaux

b o n b o n

1 2 3 4 5 6

q u e l b o n b o n b o n

1 2 3 4 5 6 7 8 9 10 11 12 13

On peut alors écrire les 7 injections strictement croissantes de bonbon dans quelbonbonbon en les présentant dans un tableau.

b o n b o n

1 2 3 4 5 6

5 6 7 8 9 10

5 6 7 8 9 13

5 6 7 8 12 13

5 6 7 11 12 13

5 6 10 11 12 13

5 9 10 11 12 13

8 9 10 11 12 13

b. Ce que désigne la variable j à la fin de l’algorithme de la 2 permet de déterminer si x est un sous-mot de y. C’est le cas si et seulement si j désigne un nombre inférieur ou égal à n. (ou si i désigne un nombre stric- tement plus grand que m). On peut former la procédure est_sous_mot en reprenant le code de la question 4.b.

est_sous_mot := proc(x,m,y,n) local i,j;

i :=1; j:=i;

(4)

while i<=m and j<=n do

while i<=m and x[i]<>y[j] do j:=j+1;

od;

i:=i+1;

od:

if j<= n then return(1) else

return(0) fi;

end proc:

#test d’appel

x := [’b’,’o’,’n’,’b’,’o’,’n’];

y := [’q’,’u’,’e’,’l’,’b’,’o’,’n’,’b’,’o’,’n’,’b’,’o’,’n’];

m := 6;

n := 13;

est_sous_mot(x,m,y,n);

5. a. On considère deux mots x et y de longueur respectives m et n.

On suppose d’abord que les deux premières lettres sont égales : x

1

= y

1

. Définissons deux parties M

0

et M

1

de M (x, y).

∀ϕ M (x, y),

( ϕ M

0

ϕ(1) = 1 ϕ M

1

ϕ(1) 6= 1 Il est clair que M

0

et M

1

partitionnent M (x, y) donc

µ(x, y) = ] M

0

+ ] M

1

L’ensemble M

0

est en bijection avec M (x

0

, y

0

) car chaque ϕ de M

0

est caractérisée par sa restriction à {2, · · · , m} qui réalise une injection de x

0

dans y

0

. Donc ] M

0

= µ(x

0

, y

0

).

L’ensemble M

1

est en bijection avec M (x

0

, y) donc ] M

1

= µ(x

0

, y). En effet, pour ϕ M

1

, ϕ(1) 6= 1 car x

1

6= y

1

donc ϕ(i) 6= 1 pour tous les i entre 1 et m car ϕ est strictement croissante. Chaque ϕ de M

1

est caractérisée par sa corestriction à {2, · · · , m} qui réalise une injection de x dans y

0

.

b. Dans un processus récursif, il faut s’assurer que l’on se ramène à des situations dans lesquelles le processus peut répondre directement sans

s’appeler lui même.

m nb de lettres de x n nb de lettres de y

Fig. 3 – Processus récursif

On sait par exemple qu’il n’y a pas d’injection lorsque m > n.

La situation est moins claire pour le cas m = 0. Il faut chercher à définir arbitrairement µ(, y) pour que les formules récursives soient valables lorsque x contient une seule lettre. On s’aperçoit alors qu’il faut poser

µ(, y) = 1 pour tous les mots y

pour que la formule soit valable avec un mot x de longueur 1. En effet lorsque x[1] = y[1] il y a toujours une injection 1 1 qui convient et il peut y avoir d’autres injections avec les autres lettres de y. On voit bien sur la figure 3 que si la procédure sait traiter directement les cas m = 0 et n < m, alors tous les cas seront atteints récursivement. On forme alors le code suivant.

#supprime la première lettre d’une liste supp := proc(l)

local i;

return([seq(l[i],i=2..nops(l))]);

end proc:

#maple accepte de considérer une liste vide

nb_inj := proc(x,m,y,n)

(5)

local xx,yy;

if m=0 then return(1) fi;

if n<m then return(0) fi;

xx:= supp(x);

yy:= supp(y);

if x[1]=y[1] then

return(nb_inj(xx,m-1,yy,n-1)+nb_inj(x,m,yy,n-1));

else

return(nb_inj(x,m,yy,n-1));

fi;

end proc:

On a formé une procédure auxiliaire qui supprime le premier mot d’une liste. Le détail de cette procédure n’était pas imposé par l’énoncé.

V. Tirage sans remise : corrigé

Fig. 4 – Tirage

1. On introduit une variable k que l’on va incrémenter de 1 à p. À chaque étape, on tient à jour un tableau B indexé de 1 à n-p+1 et contenant les nombres entre 1 et n qui n’ont pas encore été tirés selon le schéma de la figure 4.

On peut détailler la mise à jour du tableau auxiliaire.

Une variable i est incrémentée à partir de 1 jusqu’à ce que B[i]=nbt, on décale ensuite les valeurs vers la gauche.

Fig. 5 – Détail de la mise à jour du tableau auxiliaire

2. L’implémentation en une procédure maple est donnée par le code suivant : tirage := proc(p,n)

local B, C, k, it, nbt, i ; C:= array(1..p);

# initialisation de B B:= array(1..n);

for k from 1 to n do B[k] := k;

od;

# boucle principale for k from 1 to p do

it := rand(1..n-k+1)();

nbt := B[it];

C[k] := nbt;

# mise à jour du B i := 1;

while B[i] < nbt do i := i+1;

od;

while i < n-k+1 do

B[i] := B[i+1];

(6)

Fig. 6 – Partitionner i := i+1;

od;

od;

return(eval(C));

end proc:

VI. Tri rapide : corrigé

La procédure récursive principale tri_rap est simple.

tri_rap := proc(p,q) local i;

global A;

if q-p>1 then

i:= partitionner(p,q);

tri_rap(p,i);

tri_rap(i+1,q);

else

if A[p] > A[q] then truc := A[p];

A[p] := A[q];

A[q] := truc;

fi;

fi;

end proc:

La procédure partitionner est plus compliquée. Voir son diagramme en figure 6. Il est à noter que, lors du premier passage dans la boucle "principale", comme x = A[p], on sort de la boucle "j" avec une valeur > p pour j et de la boucle "i" avec la valeur p pour i. On passe donc obligatoirement au moins une fois par l’échange des valeurs, l’incrément de i, le décrément de j.

partitionner:=proc(p,q) global A;

local i,j,truc,x;

i:=p; j:=q; x := A[p];

#début boucle "principale"

while j-i >= 0 do

#début boucle "j"

while A[j]>x do j:=j-1;

od;

#fin boucle "j"

#début boucle "i"

while A[i]< x do i:= i+1;

od;

#fin boucle "i"

if i<j then truc:= A[i];

A[i]:= A[j];

A[j]:=truc;

i := i+1;

j := j-1;

fi;

od;

#fin boucle "principale"

print(p,q,x,j,A);#pour examen, à supprimer ensuite return(j);

end proc:

(7)

n:=7;

A:=array(1..n,[6,4,3,3,1,5,2]);

#partitionner(1,n,4);

tri_rap(1,n);

print(A);

Lorsque le tableau à trier est [2,3,1], le premier passage dans la boucle principale permute les deux extrèmes. Le tableau devient [1,3,2] avec i et j désignant 2.

On passe donc une deuxième fois dans la boucle principale, le j est décrémenté à 1 mais le i reste à 2 et on sort en renvoyant 1 ce qui est permis.

Vous pouvez télécharger la feuille de calcul.

Références

Documents relatifs

EPONGE

MPSI-PCSI Sciences Industrielles pour l’Ingénieur S... Annexe 02 - Trigonométrie

En cas de redistribution du document ou d’une version dérivée, il doit être partagé à son tour sous licence Creative Commons BY SA. Le police cursive utilisée est « AA

Tout comme les sons /j/ et /r/ étudiés plus, haut, le son /w/ permet dans certains cas de faire une liaison entre deux mots, afin de paraître plus authentique.. 2 ƒ /eɪ/ lorsque

Avec le corps, un élève ou 2 représentent les lettres de l'alphabet (écriture capitale) : les autres prennent la photographie afin de réaliser un abécédaire en lettres

[r]

[r]

[r]