Construction récursive de chaine de caractères⚓︎
D'après 2022, Polynésie, J1, Ex. 1
On rappelle qu'une chaine de caractères peut être représentée en Python par un texte entre guillemets ""
et que :
- la fonction
len
renvoie la longueur de la chaine de caractères passée en paramètre ; - si une variable
ch
désigne une chaine de caractères, alorsch[0]
renvoie son premier caractère,ch[1]
le deuxième, etc ; - l'opérateur
+
permet de concaténer deux chaines de caractères.
Exemples
>>> texte = "bricot"
>>> len(texte)
6
>>> texte[0]
"b"
>>> texte[1]
"r"
>>> "a" + texte
"abricot"
On s'intéresse dans cet exercice à la construction de chaines de caractères suivant certaines règles de construction.
Règle A
Une chaine est construite suivant la règle A dans les deux cas suivants :
- soit elle est égale à
"a"
; - soit elle est de la forme
"a" + chaine + "a"
, oùchaine
est une chaine de caractères construite suivant la règle A.
Règle B
Une chaine est construite suivant la règle B dans les deux cas suivants :
- soit elle est de la forme
"b" + chaine + "b"
, oùchaine
est une chaine de caractères construite suivant la règle A ; - soit elle est de la forme
"b" + chaine + "b"
, oùchaine
est une chaine de caractères construite suivant la règle B.
Fonction choice
du module random
On a reproduit ci-dessous l'aide de la fonction choice
du module random
.
>>> from random import choice
>>> help(choice)
Help on method choice in module random:
choice(seq) method of random.Random instance
Choose a random element from a non-empty sequence.
choice(seq)
renvoie un élément de seq
(qui peut être une liste) de façon pseudo-aléatoire.
La fonction A
ci-dessous renvoie une chaine de caractères construite suivant la règle A, en choisissant aléatoirement entre les deux cas de figure de cette règle.
def A():
if choice([True, False]):
return "a"
else:
return "a" + A() + "a"
1.a. Cette fonction est-elle récursive ? Justifier.
Réponse
La fonction A
s'appelle elle-même, donc A
est une fonction récursive.
1.b. La fonction choice([True, False])
peut renvoyer False
un très grand nombre de fois consécutives. Expliquer pourquoi ce cas de figure amènerait à une erreur d'exécution.
Réponse
Si choice([True, False])
renvoie False
consécutivement un nombre de fois supérieur à la limite de profondeur de récursion autorisée (1000 par défaut avec Python), dans ce cas une erreur d'exécution se produit.
Pour aller plus loin
On pourrait modifier cette limite à \(10^6\) avec le code suivant
import sys
sys.setrecursionlimit(10**6)
Dans la suite, on considère une deuxième version de la fonction A
. À présent, la fonction prend en paramètre un entier n
tel que,
- si la valeur de
n
est négative ou nulle, la fonction renvoie"a"
; - si la valeur de
n
est strictement positive, elle renvoie une chaine de caractères construite suivant la règle A avec unn
décrémenté de 1, en choisissant aléatoirement entre les deux cas de figure de cette règle.
def A(n):
if ... or choice([True, False]) :
return "a"
else:
return "a" + ... + "a"
2.a. Recopier sur la copie et compléter aux emplacements des points de
suspension ...
le code de cette nouvelle fonction A
.
Réponse
def A(n):
if (n <= 0) or choice([True, False]) :
return "a"
else:
return "a" + A(n - 1) + "a"
2.b. Justifier le fait qu'un appel de la forme A(n)
avec n
un nombre entier positif inférieur à 50, termine toujours.
Réponse
Pour \(n > 0\), l'appel à A(n)
provoque ou bien un arrêt de la fonction, ou bien un appel récursif avec le paramètre n - 1
.
Un appel à A(50)
pourrait provoquer dans le pire des cas 50 appels récursifs pour arriver à A(0)
qui termine, ou alors terminer avant !
On donne ci-après le code de la fonction récursive B qui prend en paramètre un entier n
et qui renvoie une chaine de caractères construite suivant la règle B.
def B(n):
if (n <= 0) or choice([True, False]):
return "b" + A(n - 1) + "b"
else:
return "b" + B(n - 1) + "b"
On admet que :
- les appels
A(-1)
etA(0)
renvoient la chaine"a"
; - l'appel
A(1)
renvoie la chaine"a"
ou la chaine"aaa"
; - l'appel
A(2)
renvoie la chaine"a"
, la chaine"aaa"
ou la chaine"aaaaa"
.
3. Donner toutes les chaines possibles renvoyées par les appels B(0)
, B(1)
et B(2)
.
Réponse
B(0)
renvoie"bab"
B(1)
renvoie"bab"
ou"bbabb"
.B(2)
renvoie"bab"
,"baaab"
,"bbabb"
ou"bbbabbb"
.
On suppose maintenant qu'on dispose d'une fonction raccourcir
qui prend comme paramètre une chaine de caractères de longueur supérieure ou égale à 2, et renvoie la chaine de caractères obtenue à partir de la chaine initiale en lui ôtant le premier et le dernier caractère.
Par exemple :
>>> raccourcir("abricot")
"brico"
>>> raccourcir("ab")
""
4.a. Recopier sur la copie et compléter les points de suspension ...
du code de la fonction regle_A
ci-dessous pour qu'elle renvoie True
si la chaine passée en paramètre est construite suivant la règle A, et False
sinon.
def regle_A(chaine):
n = len(chaine)
if n >= 2:
return (chaine[0] == "a") and (chaine[n - 1] == "a") and regle_A(...)
else:
return chaine == ...
Réponse
def regle_A(chaine):
n = len(chaine)
if n >= 2:
return (chaine[0] == "a") and (chaine[n - 1] == "a") and regle_A(raccourcir(chaine))
else:
return chaine == "a"
4.b. Écrire le code d'une fonction regle_B
, prenant en paramètre une chaine de caractères et renvoyant True
si la chaine est construite suivant la règle B, et False
sinon.
Réponse
def regle_B(chaine):
n = len(chaine)
if n >= 2:
return (chaine[0] == "b") and (chaine[n - 1] == "b") and (
regle_A(raccourcir(chaine)) or regle_B(raccourcir(chaine))
)
else:
return False