Parenthésage correct
Exercice conseillé en version À compléter
- Les exercices conseillés en version "Vide" sont conçus pour ressembler à un "exercice 1" des épreuves pratiques au baccalauréat de Terminale NSI.
- Les exercices conseillés en version "À compléter" sont conçus pour ressembler à un "exercice 2" des épreuves pratiques au baccalauréat de Terminale NSI.
La difficulté de l'exercice a été choisie en partant du principe qu'il est fait dans la version indiquée.
Dans cet exercice, on étend le problème de parenthésage à l'ensemble des délimiteurs, à savoir parenthèses, crochets et accolades.
On dispose de chaînes de caractères contenant uniquement :
-
des parenthèses ouvrantes
'('
et fermantes')'
, -
des crochets ouvrants
'['
et fermants']'
, -
des accolades ouvrantes
'{'
et fermantes'}'
.
Un parenthésage est correct si :
- pour chaque délimiteur, le nombre de fermants coïncide avec le nombre d'ouvrants,
- en parcourant la chaîne de gauche à droite, pour chaque délimiteur, le nombre d'ouvrants est à tout moment supérieur ou égal au nombre de fermants,
- les différents délimiteurs ne s'entre-croisent pas, par exemple
'[(])'
est incorrect.
Bien parenthésées
(2 + 4)*7
tableau[f(i) - g(i)]
#include <stdio.h> int main(){int liste[2] = {4, 2}; return (10*liste[0] + liste[1]);}
Mauvais parenthésage
(une parenthèse laissée ouverte
; pas de fermante associée à(
.{<(}>)
; mauvaise imbrication.c'est trop tard ;-)
; pas d'ouvrante associée à)
.
On souhaite programmer une fonction est_bien_delimitee
qui prend en paramètre une chaîne de délimiteurs expression
et renvoie True
ou False
selon qu'elle est correctement délimitée ou non.
On utilise un dictionnaire pour associer facilement délimiteurs fermants et ouvrants.
Exemples
>>> est_bien_delimitee('([()[]]{()})')
True
>>> est_bien_delimitee('{}[(])')
False
>>> est_bien_delimitee('[][')
False
>>> est_bien_delimitee('[]]')
False
# Tests
(insensible à la casse)(Ctrl+I)
(Alt+: ; Ctrl pour inverser les colonnes)
(Esc)
Indice 1
On utilisera une pile qui empile les ouvrants, dépile un ouvrant dès qu'un fermant est rencontré en vérifiant la correspondance, et qui ignore les autres caractères.
La classe Pile
est fournie ci-dessous. Elle est déjà "chargée" en mémoire et donc utilisable sans import dans la zone de saisie.
La classe Pile
class Pile:
def __init__(self):
"""Initialise une pile vide"""
self.valeurs = []
def est_vide(self):
"""Renvoie un booléen : la pile est-elle vide ?"""
return len(self.valeurs) == 0
def empile(self, element):
"""Empile un élément au sommet de la pile"""
self.valeurs.append(element)
def depile(self):
"""
Dépile un élément au sommet et le renvoie.
Provoque une erreur si la pile est vide.
"""
if self.est_vide():
raise ValueError("Erreur, pile vide")
else:
return self.valeurs.pop()
def __repr__(self):
"""Affiche la pile, en indiquant le sommet"""
return f"| {' | '.join([str(x) for x in self.valeurs])} | <- sommet"
Indice 2
On adopte la démarche suivante utilisant une Pile :
- on parcourt les caractères de la chaîne,
- si le caractère lu est un délimiteur ouvrant on l'empile,
- si c'est un délimiteur fermant :
- si la pile est vide, on renvoie
False
, - sinon, si le caractère dépilé n'est pas le délimiteur ouvrant du caractère lu, on renvoie
False
,
- si la pile est vide, on renvoie
- à la fin du parcours, si la pile est vide on renvoie
True
, sinonFalse
.
# Tests
(insensible à la casse)(Ctrl+I)
(Alt+: ; Ctrl pour inverser les colonnes)
(Esc)