Chaînes de caractères

\(\newcommand{\ds}{\displaystyle}\) \(\newcommand{\Frac}{\ds\frac}\) \(\renewcommand{\r}{\mathbb{ R}}\) \(\newcommand{\C}{\mathbb{ C}}\) \(\newcommand{\n}{\mathbb{ N}}\) \(\newcommand{\z}{\mathbb{ Z}}\) \(\newcommand{\Q}{\mathbb{ Q}}\) \(\newcommand{\N}{\mathbb{ N}}\) \(\newcommand{\n}{\mathbb{ N}}\) \(\newcommand{\ol}{\overline}\) \(\newcommand{\abs}[1]{\left| \,{#1} \right|}\) \(\newcommand{\pv}{\;;\;}\) \(\newcommand{\ens}[1]{\left\{ {#1} \right\}}\) \(\newcommand{\mens}[1]{\setminus\left\{ {#1} \right\}}\) \(\newcommand{\Par}[1]{\left({#1}\right)}\) \(\newcommand{\pe}[1]{\left\lfloor {#1} \right\rfloor}\) \(\newcommand{\trans}[1]{\,^t\!{#1}}\)

Chaînes de caractères

Cours

Les chaînes : premier contact

La notion de chaîne

Les chaînes de caractères permettent de stocker du texte. En première approximation, une chaîne est une succession de caractères imprimables. Cela peut être, par exemple, une phrase ou un groupe de mots, comme Le nombre 42 est magique.

On dit souvent chaîne au lieu de chaîne de caractères.

De la même façon qu’un programme peut travailler avec des entiers, il peut travailler avec des chaînes.

Sensibilité à la casse

La casse d’un caractère alphabétique est le fait que le caractère soit en majuscule ou en minuscule.

Les chaînes bonjour et bonJour sont considérées en Python comme distinctes. Si deux chaînes ont, à des positions identiques, des lettres de casses différentes, les chaînes sont considérées comme distinctes.

Chaîne littérale

Le moyen le plus immédiat d’utiliser des chaînes dans un code Python est par le biais d’une chaîne littérale :

1
2
3
4
5
s = "orange"
print(len(s))

t = 'rose'
print(len(t))
6
7
6
4

À la ligne 1, on lit "orange" : c’est une chaîne, dite littérale. A la ligne 2, on demande l’affichage du nombre de caractères de la chaîne. On lit à la ligne 6 la longueur de la chaîne.

Une chaîne est littérale lorsque

  • tous ses caractères sont placés dans le code-source,
  • la chaîne est encadrée par des caractères particuliers, appelés quotes, ici des guillemets anglo-saxons (mais il existe d’autres délimiteurs possibles).

Afficher une chaîne

Pour afficher une chaîne avec une « commande » Python, on utilisera obligatoirement la fonction print :

1
2
3
fruit = "orange"
print(fruit)
print("bonjour")
4
5
orange
bonjour
  • Lignes 2 et 4: ici, on affiche une chaîne par l’intermédiaire d’une variable.
  • Lignes 3 et 5 : affichage direct d’une chaîne littérale.
  • On notera que les délimiteurs de chaîne ne sont pas affichés.

Dans certains environnement (mode interactif, cellule Jupyter Notebook), une chaîne peut être affichée sans recours à la fonction print.

Erreur courante de débutant

Pour afficher une chaîne littérale, on fera attention de ne pas oublier les quotes autour de la chaîne :

print(bonjour)
NameError: name 'bonjour' is not defined

La notion de caractère

L’unité fondamentale d’un texte est le caractère. Un mot, une phrase est composée de caractères. On peut disposer de certains caractères en les plaçant entre guillemets, par exemple la lettre "Y" qui est en fait une chaîne d’un seul caractère (alors qu’on en écrit trois dans le code si on compte les deux guillemets).

Parmi les caractères, on trouve les caractères alphabétiques majuscules ou minuscules mais aussi tous les caractères de ponctuation, les chiffres, par exemple le chiffre "8".

On dispose aussi de caractères invisibles comme l’espace " " (taper sur la barre d’espace) ou encore le saut de ligne. Le blanc souligné _ est aussi un caractère très utilisé. Il existe aussi des caractères non imprimables et qui peuvent se retrouver dans une chaîne.

Python supporte l’encodage UTF-8 et donne donc accès à tous les caractères imaginables.

En pratique, dans un cours de débutant sur les chaînes de caractères, on essaye de ne pas avoir à utiliser des caractères tels que le guillemet ou l’apostrophe car ils ont rôle spécial pour construire des chaînes dites littérales.

La notion de chaîne littérale

Une chaîne littérale est un chaîne de caractères saisie telle quelle dans le code-source entre une paire de délimiteurs. Ainsi, "orange" est une chaîne littérale, le délimiteur étant ici un guillemet :

s = "orange"
print(s)
orange

Les délimiteurs ne font pas partie du contenu d’une chaîne littérale, comme on le voit à l’affichage.

Insistons : une chaîne littérale n’a de sens que dans un code-source puisque littéral veut dire qui s’interprète littéralement autrement dit, « lettre à lettre », et c’est bien comme cela qu’elle apparaît dans le code-source Python.

Le délimiteur de chaîne littérale le plus familier est le guillemet anglais ". Mais un autre délimiteur usuel est l’apostrophe :

1
2
3
4
s = "rose"
t = 'rose'
print(s)
print(t)
5
6
rose
rose
  • Ligne 1 : chaîne littérale entourée de guillemets
  • Ligne 2 : chaîne littérale entourée d’apostrophes
  • Lignes 5-6 : les chaînes s et t sont égales.

Pour ce qui est du contenu d’une chaîne, par défaut, les caractères d’une chaîne Python (littérale ou pas d’ailleurs) appartiennent au jeu Unicode et donc peuvent comporter des accents ou être des caractères spéciaux. Par exemple, la chaîne littérale s suivante est valide :

s = "Les pièces de 5€ n'existent pas"
print(s)
Les pièces de 5€ n'existent pas

Opérations sur des chaînes

On peut faire de nombreuses opérations sur les chaînes. Voici juste quelques exemples et qui seront détaillés ailleurs.

Nombre de caractères

Déterminer avec la fonction standard len le nombre de caractères d’une chaîne, ce qu’on appelle sa longueur :

1
print(len("anticonstitutionnellement"))
2
25
  • Ligne 1 : la fonction standard len, fournie par Python, effectue le calcul de la longueur.

Concaténer deux chaînes

L’opérateur + permet de mettre bout à bout deux chaînes :

1
print("bon" + "Jour")
2
bonJour
  • Ligne 1 : la concaténation (c’est le terme consacré) est effectuée avec l’opérateur +.
  • Ligne 2 : noter que les deux chaînes bon et Jour sont placées bout à bout, sans espace entre les chaînes.

Détail : l’expression "bon" + "Jour" est la concaténation de deux chaînes littérales et n’est pas une chaîne littérale.

Chaîne vide

Une chaîne peut être vide autrement dit ne contenir aucun caractère. Une chaîne vide peut être représentée par la chaîne littérale "" (deux guillemets collés l’un à l’autre et qui n’entourent rien). La chaîne vide est de longueur nulle :

vide = ""

print(len(vide))
0

La chaîne vide peut aussi être notée '' c’est-à-dire deux apostrophes côte-à-côte, sans espace entre les deux apostrophes :

vide = ''

# une chaîne vide a une longueur nulle
print(len(vide))
0

La chaîne vide a de nombreux usages (comme le chiffre zéro en a !). Par exemple, une chaîne vide peut être utilisée pour supprimer des caractères à l’intérieur d’une chaîne en remplaçant les caractères par une chaîne vide.

Le caractère espace

De même qu’il existe un caractère A désignant la lettre A, il existe un caractère espace, celui obtenu en tapant sur la barre d’espaces. Plus précisément, le contenu de la chaîne " " est un espace :

1
2
3
print("Bug" + "2038")
print("Bug" + " " + "2038")
print("Bug 2038")
4
5
6
Bug2038
Bug 2038
Bug 2038
  • Ligne 1 : Les chaînes "Bug" et "2038" sont concaténées sans insertion d’espace.
  • Lignes 2 et 3 : les chaînes affichées sont identiques : l’espace peut-être considéré comme une chaîne littérale (ligne 2) ou immergé dans la chaîne (ligne 3).

Invisible n’est pas vide

La chaîne " " n’est pas vide, elle contient exactement un caractère :

espace = " "
print(len(espace))
1

Le caractère espace sert aussi à créer une indentation en plaçant des « blancs » en début de lignes. Pour dessiner en mode texte, la figure ci-dessous :

         *
        ***
       *****
      *******
     *********
    ***********
   *************
  ***************
 *****************
*******************
         #
         #

il faut placer des caractères espace en début de ligne.

Le caractère saut de ligne

Dans beaucoup de langages de programmation, y compris Python, le codage du caractère saut de ligne est noté \n. L’usage de ce groupe de deux caractères permet effectivement de signifier un saut de ligne dans une chaîne (littérale) :

s = "Lundi\nMardi\nMercredi"
print(s)
Lundi
Mardi
Mercredi

On notera que le caractère saut de ligne \n n’a pas de raison d’être d’être suivi d’un espace littéral qui provoquerait un effet peut-être non désiré :

1
2
s = "Lundi\n Mardi\nMercredi"
print(s)
3
4
5
Lundi
 Mardi
Mercredi
  • Ligne 1 : noter l’espace dans le code source, dans la chaîne littérale, juste avant le mot Mardi.
  • Ligne 4 : l’espace est compté dans la chaîne et visible à l’affichage.

Bien que le caractère littéral représentant un saut de ligne s’écrive avec deux caractères, ces deux caractères sont insécables et ils comptent pour un caractère dans la longueur de la chaîne vue comme objet Python. Ainsi :

s="rose\nbleu"
print(s)
print(len(s))
rose
bleu
9

Plusieurs sauts de ligne

Pour aérer un texte, on peut souhaiter y placer plusieurs sauts de ligne l’un après l’autre. Si on place côte-à-côte deux caractères \n, on effectue deux passages à la ligne, ce qui va créer une ligne blanche :

texte = "rose\n\nkiwi"
print(texte)
rose

kiwi

Une ligne blanche n’est jamais vide et est constituée d’au moins un caractère, le saut de ligne et éventuellement des espaces en début de ligne.

Concaténation et répétition de chaînes

On peut concaténer des chaînes, c’est-à-dire les mettre bout à bout. La concaténation de chaînes est effectuée avec l’opérateur + :

1
2
3
4
5
6
a = "Rose"
b = "Rouge"
c = "Rome"
s = a + b + c
print(s)
print(a, b, c)
7
8
RoseRougeRome
Rose Rouge Rome
  • Ligne 4 : s est la concaténation des chaînes a, b et c.
  • Lignes 5 et 8 : la concaténation des chaînes crée une nouvelle chaîne et préserve les chaînes initiales.

On peut aussi concaténer n fois une chaîne avec elle-même avec l’opérateur *

1
2
3
4
5
a = "Rose"
r = 3 * a
print(r)
print(a * 3)
print(2 * a *2)
6
7
8
RoseRoseRose
RoseRoseRose
RoseRoseRoseRose
  • Ligne 3 ou 4 : a est répétée 3 fois
  • Lignes 5 : on peut multiplier des deux côtés.

On peut aussi panacher addition et multiplication :

a = "Rose"
b = "Rouge"
c = "Rome"
s = 2 * (c + a + ' ') + 2 * (c + b + ' ')
print(s)
RomeRose RomeRose RomeRouge RomeRouge

Concaténation et produit par zéro

L’opération 0 * s renvoie la chaîne vide et 1 * s. On peut en déduire une astuce pour mettre un nom au pluriel en ajoutant, selon l’effectif, un "s" terminal :

for val in (0, 1, 7):
    print(val, "bille" + (val > 1)*"s")
0 bille
1 bille
7 billes

Voici 3 autres façons de réaliser la même opération

for val in (0, 1, 7):
    print(val, "bille" + ["s", ""][val < 2])

print("---------------")
for val in (0, 1, 7):
    print(val, "bille" + ("" if val < 2 else 's'))

print("---------------")
for val in (0, 1, 7):
    print(val,  f"bille{'s'[val<2:]}")

et qui affiche :

0 bille
1 bille
7 billes
---------------
0 bille
1 bille
7 billes
---------------
0 bille
1 bille
7 billes

Chaînes égales

L’opérateur == permet de comparer deux chaînes pour savoir si elles ont ou pas exactement les mêmes caractères et dans le même ordre :

1
2
3
4
print("ROSE" == "R0SE")
print("RoseRose" == "Rose" + "Rose")
print("Rose" == "rose")
print("ROSE" == 'ROSE')
5
6
7
8
False
True
False
True
  • Ligne 1 : Malgré les apparences, les chaînes sont distinctes : à l’indice 1, l’une utilise la lettre O majuscule et l’autre un zéro.
  • Ligne 2 : "Rose" + "Rose" est la concaténation de deux chaînes.
  • Ligne 3 : Pour que deux caractères soient égaux, il faut déjà qu’ils aient la même casse, ce qui n’est pas le cas de la lettres initiale.
  • Ligne 4 : Des délimiteurs apostrophes ou guillemets n’ont pas d’influence sur l’égalité de chaînes.

Attention que l’égalité de deux chaînes est une opération ayant une complexité cachée. En effet, pour savoir si deux chaînes sont égales ou pas, l’interpréteur Python compare terme à terme les éléments des deux chaînes jusqu’à ce que deux caractères soints distincts ou bien qu’une des chaînes ne possède plus d’élément à examiner.

Donc la comparaison de deux chaînes de longueur chacune 1000, peut nécessiter jusqu’à 1000 comparaisons. Ainsi, l’opérateur == entre deux chaînes peut être coûteux (en réalité, c’est moins simple que ça, cf. implicit Interning).

Recherche de sous-chaînes avec in

Soit la chaîne

s = "xyxABCyyyxABCxyyxABCxyx"

La chaîne 'ABC' est une sous-chaîne de s et elle y apparaît même 3 fois. Rechercher une sous-chaîne dans une chaîne est une opération classique en programmation et appelée recherche de motif, en anglais pattern matching. Les caractères de la sous-chaîne doivent être contigus et non séparés ; ainsi la chaîne ABC n’est pas considérée comme étant une sous-chaine de la chaîne xxxAxxxxBxxCxxxx.

Une première possibilité de détection d’une sous-chaîne est d’utiliser l’opérateur in qui va renvoyer True ou False selon la présence ou l’absence de la sous-chaîne :

s = "xyxABCyyyxABCxyyxABCxyx"

print("ABC" in s)
print("AbC" in s)
True
False

En première approximation, voici comment se fait la recherche de la sous-chaîne : elle se poursuit jusqu’à obtention d’une occurrence de la sous-chaîne ou alors lorsque la fin de la chaîne est atteinte. Si une occurrence est découverte, la recherche s’interrompt.

Pour entrer dans les détails d’implémentation en CPython, il semble que l’opérateur in fasse appel aux algorithmes de Boyer-Moore et Horspool. L’examen du code-source de la fonction PyUnicode_Contains montre que des fonctions spécialisées de recherche sont invoquées, par exemple ucs1lib_find, qui font appel à la fonction FASTSEARCH.

Accès aux caractères d’une chaîne

On peut accéder en lecture individuellement aux caractères d’une chaîne à l’aide d’un indice entier :

p = "Jupiter"

# le premier caractère de la chaîne p
print(p[0])

# le troisième caractère de la chaîne p
print(p[2])

# la longueur de la chaîne
n = len(p)
print(n)

# Dernier caractère de la chaîne p
print(p[n - 1])
J
p
7
r

Les caractères d’une chaînes sont numérotés de la gauche vers la droite. Ces numéros sont appelés des indices ; la numérotation commence à 0 (et non pas à 1) et se termine à n-1n désigne le nombre total de caractères.

On accède à chaque caractère de la liste avec l’opérateur [] d’indexation.

Le fait de pouvoir accéder à tous les caractères d’une chaîne par des entiers consécutifs se traduit en disant que les chaînes de caractères sont du type séquence.

Il est possible d’utiliser des indices négatifs, ce qui est parfois à l’origine de bugs pour ceux qui ne connaissent pas leur existence.

Dépassement d’indice dans une chaîne

Comme pour les listes, un indice de chaîne trop grand entraîne la levée d’une exception :

1
2
3
4
z = "orange"
c = z[10]

print(c)
5
6
    c = z[10]
IndexError: string index out of range
  • Ligne 6 : une erreur d’indice est signalée
  • Ligne 2 : la variable c désignerait le caractère à l’indice 10 alors que l’indice maximal dans c est 5 puisque la chaîne z est de longueur 6.
  • Ligne 2 : L’opération z[10] est en fait interdite, on tente d’accéder en lecture à un caractère qui n’existe pas.
  • Lignes 5-6 : Le message d’erreur explique que l’indice 10 est en dehors de la plage d’indices possibles.

Tenter d’accéder en simple lecture à un caractère d’une chaîne avec un indice ne correspondant pas à un élément de la chaîne conduit à une erreur, de type indexError et qualifiée de débordement d’indice. C’est le même problème que pour les listes.

Boucle for : parcours de chaînes

Une chaîne est une séquence et peut être parcourue, sans indice, par une boucle for. Voici un exemple de parcours d’une chaîne avec une boucle for :

for c in "ALIBABA":
    print(c*2)
AA
LL
II
BB
AA
BB
AA

C’est le même principe que pour les listes, il est possible de faire un parcours sans recourir à un indice.

Il est aussi possible de parcourir la chaîne par indices :

s="ALIBABA"

for i in range(len(s)):
    print(s[i]*2)
AA
LL
II
BB
AA
BB
AA

Cela peut être justifié dans certaines situations (par exemple si on doit comparer un caractère au suivant ou au précédent) où l’usage recommande d’utiliser enumerate, voir cette explication.

Créer une chaîne à partir de la chaîne vide

Soit à construire une chaîne z dont les caractères sont exactement les consonnes d’une chaîne s donnée. Par exemple, si s est la chaîne broccoli alors la chaîne cherchée est brccl.

Pour cela, il suffit de parcourir la chaîne s et d’ajouter à une chaîne initialement vide (disons z) le caractère courant de s si le caractère est une consonne (et donc s’il n’est pas une voyelle). D’où le code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
s= "broccoli"
VOYELLES ="aeiouy"
z = ""

for c in s:
    if c not in VOYELLES:
        z += c

print(s)
print(z)
11
12
broccoli
brccl
  • Lignes 3, 10 et 12 : la chaîne à construire est initialement vide.
  • Lignes 5-7 : la chaîne s est agrandi au fur et à mesure par ajout d’une consonne.

C’est le même type de construction que pour une liste initialement vide à laquelle on applique la méthode append.

Modifier une chaîne

Les caractères d’une chaîne ne sont pas modifiables :

1
2
3
s = "taTou"
s[2] = "B"
print(s)
4
TypeError: 'str' object does not support item assignment
  • Ligne 2 : on tente de changer le caractère T de la chaîne "taTou" en "B".

Par construction, les chaînes de caractères sont de type immuable : leur contenu ne peut être modifié. Non seulement, on ne peut pas changer un caractère en un autre, mais on ne peut en supprimer ni en rajouter, à quelque endroit que ce soit.

Exercices

Doubler les lettres

À partir d’une chaîne telle que bali, on veut construire la chaîne bbaallii.

Plus précisément, étant donné une chaîne de caractères, sans accent, construire une nouvelle chaîne telle que chaque caractère de la chaîne initiale soit doublé.

Distance de Hamming

Étant donné deux chaînes de caractères s et t, supposées de même longueur, on appelle distance de Hamming entre s et t, le nombre de positions où les chaînes ont des caractères différents. Par exemple, si s et t sont les chaînes

s = "pointes"
t = "voisins"

alors, la distance de Hamming entre ces deux chaînes est 4.

Ecrire une fonction hamming(s, t) qui renvoie la distance de Hamming entre deux chaînes de caractères s et t de même longueur. Par exemple, si s et t sont les chaînes ci-dessus, alors hamming(s, t) = 4.

Doubler les voyelles sauf certaines

On donne un mot M formé de lettres minuscules sans accent. On veut construire un mot MM qui s’obtient à partir de M en en gardant les mêmes lettres sauf que chaque voyelle est doublée à l’exception des deux cas suivants :

  • la voyelle est la dernière lettre du mot,
  • la voyelle est suivi de la lettre n.

Les voyelles sont parmi les lettres a, e, i, o, u et y.

Voici quelques exemples d’exécution :

enduire : enduuiire
ordinateur : oordinaateeuur
nsi : nsi
lenteur : lenteeuur
python : pyython
java : jaava
c : c

On pourra parcourir les caractères de mot en utilisant une boucle for (avec ou sans indice mais la faire sans indice oblige à mémoriser le caractère précédent).

Cet exercice provient d’une question posée sur le forum Python d’OpenClassrooms.

Changer OU en O et O en OU

On donne un mot M formé de lettres majuscules sans accent. On veut construire un mot MM qui s’obtient à partir de M en en gardant les mêmes lettres sauf que

  • si une lettre O est suivie de la lettre U, la lettre U ne sera pas gardée (par exemple NOUNOU deviendra NONO),
  • si une lettre O n’est pas suivie de la lettre U, la lettre O sera remplacée par OU (par exemple DODO deviendra DOUDOU).

Voici quelques exemples d’exécution :

O : OU
U : U
NOUNOU : NONO
DODO : DOUDOU
OO : OUOU
OUOU : OO
OO : OUOU
OUOUO : OOOU
UOOU : UOUO

On pourra parcourir les caractères de mot en utilisant une boucle for avec indice et utiliser un drapeau ou passant à True lorsqu’une lettre O est rencontrée et qu’elle est suivie d’un U. Il est aussi possible de parvenir au même résultat en utilisant un parcours sans indice, en gérant le caractère précédent avec une variable prv, initialisée à la chaîne vide (par exemple).

Cet exercice provient d’une question posée sur le forum Python d’OpenClassrooms.

Palindrome

  1. Ecrire une fonction inverser(ch) qui prend une chaîne en argument et renvoie cette chaîne mais écrite à l’envers. Par exemple, la chaîne CITOYEN doit renvoyer la chaîne NEYOTIC.
  2. Le mot RADAR est un palindrome : quand on lit ses lettres de la droite vers la gauche, le mot est inchangé. Ecrire une fonction estPalindrome(ch) qui prend une chaîne ch en argument et renvoie True si la chaîne ch est un palindrome, et False sinon. On utilisera la question précédente. On supposera que la chaîne ch ne contient que des caractères alphabétiques majuscules et sans accent. On rappelle que Python permet de comparer des chaînes.

Chaînes formées seulement de lettres parmi a ou b

On appellera babachaîne toute chaîne constituée de caractères uniquement parmi les deux lettres minuscules a ou b. Par exemple, la chaîne bbabaaab ou encore la chaîne bb sont des babachaîne, mais pas dada (qui contient le caractère d).

  1. Soit une babachaîne C. Écrire un code Python qui renvoie le nombre d’occurrences de la lettre a dans la chaîne C. Par exemple,
    • si C est la chaîne ababa, le programme doit renvoyer 3;
    • si C est la chaîne bbb, le programme doit renvoyer 0.
  2. Soit une chaîne babachaîne C de longueur impaire. Écrire un code Python qui renvoie la lettre la plus présente dans la chaîne C. Par exemple,
    • si C est la chaîne ababa, le programme doit renvoyer a ;
    • si C est la chaîne bbb, le programme doit renvoyer b.

Mots les plus longs

On donne une liste de mots et on demande de renvoyer la liste des mots ayant la longueur maximum dans cette liste. Par exemple, si la liste a pour contenu

poire
salade
pomme
vanille
salade
cerise
bégonia
radis
ananas
tomate
poireau

un mot le plus long a pour longueur 7 et les mots de la liste ayant cette longueur sont :

vanille
bégonia
poireau

Les mots ci-dessus sous forme de liste :

['poire', 'salade', 'pomme', 'vanille', 'salade', 'cerise',
'bégonia', 'radis', 'ananas', 'tomate', 'poireau']

Conjuguer un verbe du premier groupe

On donne un verbe régulier du premier groupe (qui se terminer par ER), par exemple, danser. Ecrire un code qui affiche la conjugaison de ce verbe au présent de l’indicatif. Par exemple, avec danser, le code affichera :

je danse
tu danses
il/elle danse
nous dansons
vous dansez
ils/elles dansent

On pourra créer une liste de terminaisons et une liste de pronoms.

Bijou, caillou, etc

On donne un nom commun, au singulier, par exemple le mot POIRE, sous forme de chaîne de caractères alphabétiques majuscules. On demande d’afficher ce mot au pluriel. On suppose que le mot satisfait une des deux situations suivantes :

  • il admet un pluriel régulier, qui s’obtient en ajoutant un s
  • il se termine par OU auquel cas son pluriel n’est pas régulier si le nom fait partie de la liste d’exceptions données ci-dessous et auquel cas il faut ajouter un x et non pas un s.

La liste des exceptions est la suivante :

BIJOU, CAILLOU, CHOU, GENOU, HIBOU, JOUJOU, POU

Par exemple,

  • si le mot est POIRE, il faudra construire le mot POIRES
  • si le mot est CHOU, il faudra construire le mot CHOUX
  • si le mot est TOUTOU, il faudra construire le mot TOUTOUS

On écrira une fonction pluriel(nom) qui renverra le mot au pluriel.

Dernières lettres d’un mot

Ecrire une fonction term(mot, k) qui renvoie la partie d’un mot formée de ses k dernières lettres. Si k dépasse la longueur du mot, la fonction renverra le mot en entier.

Par exemple, si mot = "orange" alors term(mot, 4) renvoie "ange".

Mots en lignes, en colonnes

On donne une liste de mots, tous de même longueur. On demande d’afficher les mots, sous forme de tableau 2D et des deux façons suivantes :

  • les mots sont écrits horizontalement
  • les mots sont écrits verticalement, avec un trait vertical entre chaque colonne

Par exemple, si la liste des mots est :

mots = ["POIRE", "SAVON", "LAVER", "LABEL"]

alors l’affichage horizontal sera :

POIRE
SAVON
LAVER
LABEL

et l’affichage vertical sera :

P|S|L|L|
O|A|A|A|
I|V|V|B|
R|O|E|E|
E|N|R|L|

Un trait vertical s’obtient avec la combinaison Alt Gr + 6.

Triangle en mode texte

On donne un entier \(\mathtt{n\geq 2}\) et on demande d’écrire un code qui dessine en mode texte un triangle tel que chaque côté soit constitué de \(\mathtt{n}\) astérisques. Par exemple, pour \(\mathtt{n=4}\)

   *
  * *
 *   *
* * * *

ou pour \(\mathtt{n=5}\) :

    *
   * *
  *   *
 *     *
* * * * *

À gauche d’une astérique, quand il semble y avoir du vide, c’est qu’il y a un caratère espace. La base du triangle alterne un caractère espace et une astérique. Il est attendu que le code ne contienne aucune instruction if.

Découper en mots

On donne une chaîne de caractères s et on demande de construire la liste des mots apparaissant dans cette chaîne, en respectant leur ordre d’apparition. Par exemple, si la chaîne est

"l'artichaut, le chou-fleur, la poire d'italie ..."

la liste des mots à afficher sera :

['l', 'artichaut', 'le', 'chou', 'fleur', 'la', 'poire', 'd', 'italie']

Pour simplifier, un mot sera une suite formée uniquement de caractères alphabétiques minuscules. On pourra utiliser la chaîne suivante

ALPHA="azertyuiopmlkjhgfdsqwxcvbn"

Immatriculation valide

Voici un exemple d’immatriculation de véhicule en France : 42-TDA-08. Une immatriculation française est constituée de 9 caractères, qui se décomposent, de la gauche vers la droite en :

  • deux chiffres
  • un tiret
  • trois lettres majuscules,
  • un tiret
  • deux chiffres

Écrire un programme qui, à partir d’une suite de caractères, renvoie True ou False selon que cette suite constitue, oui ou non, une immatriculation valide.

Voici des exemples de réponses attendues

Immatriculation Réponse
42-TDA-8 False
TDA-452-AbC False
81-ABC-75 True

On pourra utiliser les chaînes suivantes :

DIGITS = "0123456789"
ALPHA = "AZERTYUIOPLKJHGFDSQWXCVBN"

Afficher un numéronyme

On va décrire ci-dessous un procédé de compression de mot. On donne une chaîne de caractères, par exemple s = "Kubernetes" et on demande d”afficher une nouvelle chaîne S, avec notre choix de s, ce sera S = "K8s". La règle de construction de la chaîne S est précisée ci-dessous :

  • si s a au moins trois éléments :

    • le premier et le dernier caractères de S sont identiques à ceux de s ;
    • les caractères de S strictement entre le premier et de dernier caractère de S représentent le nombre d’éléments de s strictement compris entre les extrémités de s
  • sinon S = s.

Voici quelques exemples de comportement :

Kubernetes -> K8s
Python -> P4n
Internationalization -> I18n
globalization -> g11n

On ne demande pas de construire S, on demande juste de l’afficher. On rappelle que l’on peut afficher des chaînes concaténées avec la fonction print :

print("Pomme", end='')
print("Pink", end='')
print("Lady")
PommePinkLady

Mot de passe valide

Un mot de passe m est considéré comme sûr si les conditions suivantes sont réalisées :

  • m est formé d’au moins huit caractères ;

  • m contient au moins :

    • une lettre minuscule
    • une lettre majuscule
    • un chiffre
    • un signe de ponctuation parmi le tiret, le point d’exclamation ou d’interrogation, la virgule, le point, le point-virgule, le deux-points, l’astérisque et le tilde.

Créer une variable mot_de_passe_valide qui vaut True si le mot de passe m est sûr et False sinon.

On pourra utiliser les chaînes da caractères suivantes :

MIN = 'azertyuiopmlkjhgfdsqwxcvbn'
MAJ = 'AZERTYUIOPMLKJHGFDSQWXCVBN'
CHIF = '0123456789'

# Ponctuation
PONCT = '-!?,.;:*~'

Afficher les occurrences d’un sous-mot

On donne une chaîne s, de caractères majuscules et on demande d’afficher toutes les occurrences du sous-mot LOL dans la chaîne s, les autres lettres étant remplacées par des points.

Par exemple si s = "LALAOOLOLA" alors le programme devra afficher :

L...O.L...
L...O...L.
L....OL...
L....O..L.
L......OL.
..L.O.L...
..L.O...L.
..L..OL...
..L..O..L.
..L....OL.
......LOL.

On utilisera le fait que la chaîne à détecter est courte.

L’idée de exercice est inspirée d’un problème de Codeforces.

Métathèses

Ecrire un code qui effectue un échange aléatoire de deux lettres parmi toutes les lettres du mot sauf la première. A moins que cela soit impossible, le mot généré doit être différent du mot initial. Par exemple, le mot programmation pourra générer le mot prorgammation.

Si on applique cette modification à la phrase suivante :

La raison du plus fort est toujours la meilleure, nous l’allons montrer tout à l’heure

cela pourrait produire

La raisno du puls fotr ets toujuors la muilleere, nosu la’llons mrntreo totu à l’reuhe

Lettres découvertes

On propose à un joueur de découvrir un mot secret, par exemple CITRONNIER. Au début, les lettres du mot secret sont cachées par des astériques :

**********

Si le joueur propose le caractère R, il obtient la réponse :

***R*****R

S’il continue avec N, il obtiendra :

***R*NN**R

S’il propose maintenant la lettre U, il obtiendra le même résultat que ci-dessus car U n’est pas dans le mot secret.

On donne une chaîne représentant un mot, par exemple le mot CITRONNIER. On donne une chaîne essais, par exemple essais = "RNU". Les lettres de cette chaîne représentent les lettres successives proposées par le joueur. On demande d’afficher le mot au fur et à mesure que les lettres sont proposées.

Par exemple, si le mot est CITRONNIER et si la suite des lettres est essais="RNUIB" alors le programme devra afficher :

**********
***R*****R
***R*NN**R
***R*NN**R
*I*R*NNI*R
*I*R*NNI*R

Séparer par des majuscules

On donne une phrase écrite en minuscules, et dont les mots sont séparés par un ou plusieurs espaces, par exemple

phrase ="la   vie est      un long fleuve tranquille"

et on demande de produire une chaîne issue de la phrase et telle que les mots soient accollés les uns aux autres mais commencent par une majuscule. Avec l’exemple ci-dessus, on obtiendra

LaVieEstUnLongFleuveTranquille

Pour produire un caractère majuscule à partir d’un caractère minuscule, on utilisera la méthode upper, comme illustré ci-dessous :

a_min = "a"
a_maj = a_min.upper()

print(a_maj)

qui affiche

A

Pour répondre à la question, on partira d’une chaîne reponse contenant uniquement le premier caractère écrit en majuscule, on parcourra la phrase avec un indice, on fera croître la chaîne reponse en utilisant un drapeau booléen ESP qui indiquera si oui ou non le parcours est en train d’examiner une suite d’espaces.

Les deux premiers mots

On donne une chaîne de caractères contenant au moins un espace, par exemple

s = "Le travail est un trésor".

On demande d’en extraire la sous-chaîne formée de deux premiers mots, un mot étant délimité par le début ou la fin de la chaîne ou par un espace.

Par exemple, si s = "Le travail est un trésor" alors la chaîne à extraire est "Le travail".

On pourra parcourir avec une boucle while la chaîne s à la recherche du premier caractère espace puis avec une autre boucle while le caractère espace suivant ou la fin de la chaîne (on peut aussi n’utiliser qu’une boucle while et compter le nombre d’espaces).

Supprimer les espaces autour d’une chaîne

Ecrire une fonction strip(s) qui partant d’une chaîne de caractères \(\mathtt{s}\) renvoie la chaîne identique à s sauf que les caractères Espace placés en début et fin de la chaîne s ont été retirés. Pour cela, on pourra procéder comme suit :

  • chercher le plus petit indice i d’un caractère de s différent du caractère " " (si s n’est formée que d’espaces, on posera que i vaut la longueur de la chaîne) ;
  • chercher le plus grand indice \(\mathtt{j\geq i}\) d’un caractère de s différent du caractère " "
  • construire la sous-chaîne de s entre l’indice i et l’indice j.

On utilisera une boucle while pour les deux premières étapes.

Nettoyer un message

On donne un message sous forme d’une chaîne de caractères. On doit récrire ce message mais en ignorant :

  • tout caractère qui est un espace
  • toute portion du message placée entre deux astériques consécutives, astérisques incluses.

Par exemple, le message suivant

VI  C*DEST*TO *TREM BLER*IRE

sera transformé en le message

VICTOIRE

Ecrire un code qui tranforme un message donné comme indiqué ci-dessus. On parcourra la chaîne et on utilisera un drapeau indiquant si le parcours se trouve, oui ou non, dans une portion située entre deux astérisques.

Cet exercice est inspiré de la sélection au concours Prologin 2020.

Séparer par blocs de 3 chiffres

On donne un entier positif sous forme d’une chaîne de caractères formée exclusivement de chiffres entre 0 et 9, par exemple la chaîne

"14959787070"

On demande de construire une chaîne de caractères représentant le même nombre sauf que ses chiffres sont reproupés par paquets de 3 à partir du chiffres des unités, les blocs étant séparés par des caractères _ (un blanc souligné).

Voici quelques exemples de comportements du programme :

0 → 0
5 → 5
42 → 42
142 → 142
2038 → 2_038
149597870 → 149_597_870
14959787070 → 14_959_787_070

On pourra examiner le reste de n modulo 3 où n est le nombre de chiffres.

Supprimer la virgule et les zéros inutiles

On donne un entier positif sous forme d’une chaîne de caractères s formée de chiffres entre 0 et 9 et éventuellement d’une virgule, par exemple :

"00042"
"2030,0"
"2030,00000"
"2030,"
"2030"
"00000"
"000,00"

Le nombre donné est un entier positif donc une chaîne telle que s = "3,14" est exclue. On demande de représenter le même entier par une chaîne S ne contenant ni virgule ni zéros inutiles. Les zéros dits inutiles se trouvent en tête du nombre ou en fin de nombre, après la virgule. On écrira une fonction supprimer(s). Voici quelques exemples d’exécution du programme :

s = 00042 → S = 42
s = 2030,0 → S = 2030
s = 2030,00000 → S = 2030
s = 2030, → S = 2030
s = 2030 → S = 2030
s = 00000 → S = 0
s = 000,00 → S = 0

Chaîne représentant un entier ou pas

On donne une chaîne de caractères s représentant un nombre positif ou nul x. On admettra que la chaîne contient exclusivement des chiffres entre 0 et 9 et éventuellement le caractère virgule, présent au plus une fois. On demande de créer un booléen qui vaut True si le nombre s’évalue en un nombre entier et False sinon. Voici quelques exemples de comportement du programme :

s = "42" → True
s = "2030,0" → True
s = "2030," → True
s = "2030,00000" → True
s = "3,140000" → False

Nom valide ou pas

On donne une chaîne de caractères alphanumériques (chiffres et lettres non accentuées minuscules ou majuscules) et on considère que la chaîne est valide si elle vérifie les trois conditions suivantes :

  • elle commence par une lettre majuscule
  • elle comporte au maximum 2 caractères successifs identiques
  • sa taille est d’au minimum 5 caractères et, au maximum, 15 caractères (bornes incluses).

Noter que deux lettres, l’une minuscule et l’autre majuscule, sont considérées comme différentes.

On donne une chaîne et on demande de construire une fonction isValid(s) qui renvoie True si la chaîne s est valide et False autrement.

Voici quelques exemples de comportement du programme :

Abricot : Valide
Abricot42 : Valide
AbbriCOOot : Valide
Abri : Invalide
abricot : Invalide
42abricot : Invalide
Abricot0123456789 : Invalide
Abbbricot : Invalide
Abricot3000 : Invalide

On pourra utiliser la chaîne suivante :

ALPHA = "AZERTYUIOPLMKJHGFDSQWXCVBN"

Cet exercice est inspiré de l’exercice Joli nom donné en 1/2 finale de Prologin 2018.

Mot dans une phrase à une position donnée

On donne une chaîne de caratères représentant une phrase formée de mots. Un mot, par définition est entouré d’espaces ou est déterminé par le début ou la fin de la chaîne. On donne un indice valide \(\mathtt{k\geq 0}\) de la chaîne. On demande d’écrire une fonction isoler(s, k) qui détermine l’unique mot dont une des lettres est à l’indice donné. Si l’indice k indique dans s un caractère espace, la fonction renverra la chaîne vide.

L”exercice a été proposé sur le forum du site OpenClassrooms.

Voici quelques exemples d’exécution sur la chaîne " Hello You " :

k = 0
lettre :
Mot :
----------
k = 1
lettre : H
Mot : Hello
----------
k = 2
lettre : e
Mot : Hello
----------
k = 3
lettre : l
Mot : Hello
----------
k = 4
lettre : l
Mot : Hello
----------
k = 5
lettre : o
Mot : Hello
----------
k = 6
lettre :
Mot :
----------
k = 7
lettre : Y
Mot : You
----------
k = 8
lettre : o
Mot : You
----------
k = 9
lettre : u
Mot : You
----------
k = 10
lettre :
Mot :
----------

Découper un texte en lignes

On donne un texte sous la forme d’une chaîne de caractères ne contenant aucun saut de ligne. On testera son code sur la chaîne s donné dans le code Python suivant :

s = ("Lorem ipsum dolor sit amet, consectetur ad"
     "ipiscing elit. Maecenas eu nisl id lectus "
     "malesuada dignissim. Etiam leo justo, dapi"
     "bus non purus tempus, consequat luctus jus"
     "to. Donec id tincidunt odio, in consequat "
     "metus. In hac habitasse platea dictumst. I"
     "n efficitur consectetur luctus. Fusce et a"
     "ccumsan arcu. Nam convallis at odio nec he"
     "ndrerit. Cras pulvinar, enim in viverra da"
     "pibus, ante risus lobortis nisl, vel biben"
     "dum massa velit nec nulla. Sed viverra ris"
     "us et diam pulvinar, in dignissim ex hendr"
     "erit. Sed ipsum lacus, porttitor vitae mol"
     "estie ultrices, semper in magna.")

print(s)

Malgré les apparences, ce texte ne contient aucun saut de ligne, cela se voit à l’affichage produit par la fonction print.

  1. On veut découper ce texte en lignes qui fassent exactement 30 caractères, sauf éventuellement la dernière ligne. Le texte doit être préservé : on ne fait qu’ajouter des caractère sauts de lignes \n.

    Écrire un code qui renvoie une chaîne de caractères représentant le nouveau texte auquel on a ajouté des sauts de ligne. Voici les 10 premières lignes pour l’exemple ci-dessus :

    Lorem ipsum dolor sit amet, co
    nsectetur adipiscing elit. Mae
    cenas eu nisl id lectus malesu
    ada dignissim. Etiam leo justo
    , dapibus non purus tempus, co
    nsequat luctus justo. Donec id
     tincidunt odio, in consequat
    metus. In hac habitasse platea
     dictumst. In efficitur consec
    tetur luctus. Fusce et accumsa
    
  2. On veut cette fois découper le texte en un nombre minimum de lignes, qui fassent au plus 30 caractères et en sorte que les sauts de ligne ne coupent pas un mot en deux. Le texte doit être préservé : on ne fait qu’ajouter des sauts de lignes. On garantit qu’il n’existe aucun mot dans le texte formé de plus de 30 caractères.

    Écrire un code qui renvoie une chaîne de caractères représentant le nouveau texte auquel on a ajouté des sauts de ligne. Voici les 10 premières lignes pour l’exemple ci-dessus :

    Lorem ipsum dolor sit amet,
    consectetur adipiscing elit.
    Maecenas eu nisl id lectus
    malesuada dignissim. Etiam
    leo justo, dapibus non purus
    tempus, consequat luctus
    justo. Donec id tincidunt
    odio, in consequat metus. In
    hac habitasse platea
    dictumst. In efficitur
    

Répéter un motif et tronquer

On donne une chaîne de caractères s, par exemple Orange. On donne un entier positif n et on demande de construire la chaîne S obtenue si on répétait bout à bout la chaîne s et qu’on ne conservait que les n premiers caractères de la répétition.

Par exemple, pour la chaîne s = Orange et n = 39, on obtient pour S la chaîne :

OrangeOrangeOrangeOrangeOrangeOrangeOra

Cet exercice est la version pour les chaînes de caractères d’un exercice antérieur intitulé Dupliquer une liste sur une certaine longueur et qui s’appliquait aux listes.