---
jupytext:
  text_representation:
    extension: .md
    format_name: myst
    format_version: 0.13
kernelspec:
  display_name: Python 3 (ipykernel)
  language: python
  name: python3
learning:
  objectives:
    understand: [fonction, "param\xE8tre", return, float, boucle for, compteur, accumulateur]
    apply: [fonction, documentation, boucle for, affectation]
  prerequisites:
    apply: [expression, affectation, boucle for, fonction]
---

+++ {"nbgrader": {"grade": false, "grade_id": "cell-a1cea05ac1387514", "locked": true, "schema_version": 3, "solution": false}}

# TP : Créer un moteur de censure de texte (1/4)


Imaginez que vous développez un outil qui doit censurer certains mots dans un texte (par exemple des insultes ou des termes interdits).
Quand l’outil détecte un mot interdit, il doit le remplacer par des `*`.

:::{admonition} Exemple
Texte : `Ce chien est méchant.`
Mot interdit : `chien`.
Résultat : `Ce ***** est méchant.`
:::


Dans ce TP, vous allez progressivement construire un mini-moteur de censure, étape par étape.

+++ {"nbgrader": {"grade": false, "grade_id": "cell-670b85df3798f432", "locked": true, "schema_version": 3, "solution": false}}

## Rappel : les chaînes de caractères en Python

+++

Une chaîne de caractères (ou `string`) est une suite de symboles entourés de guillemets :

```{code-cell} ipython3
s = "Bonjour"
```

On peut accéder aux caractères grâce aux **indices** (index) :

```{code-cell} ipython3
print(s[0])   # B
print(s[1])   # o
```

Les indices commencent à **0**.

La fonction `len(s)` renvoie la longueur de la chaîne :

```{code-cell} ipython3
len("Salut")   # 5
```

On peut lire une chaîne caractère par caractère avec une **boucle for** :

```{code-cell} ipython3
for car in "chat":
    print(car)
```

On peut aussi parcourir une chaîne en utilisant ses **indices** :

```{code-cell} ipython3
mot = "chat"
for i in range(len(mot)):
    print("Indice", i, "→", mot[i])
```

Pour construire une nouvelle chaîne, on utilise souvent un **accumulateur**. Voilà un exemple où l'on remplace les espaces d'une chaîne de caractères par des tirets :

```{code-cell} ipython3
texte = "le chat dort"
résultat = ""

for car in texte:
    if car == " ":              # Si c’est un espace
        résultat = résultat + "-"   # On ajoute un tiret
    else:
        résultat = résultat + car   # Sinon, on garde la lettre

résultat
```

:::{warning} Attention
 
 Les chaînes sont immutables : on ne peut pas modifier un caractère directement, il faut créer une nouvelle chaîne.

:::

+++ {"nbgrader": {"grade": false, "grade_id": "cell-8ce9f4aa74ff1ade", "locked": true, "schema_version": 3, "solution": false}}

## Partie 1 : Fonctions de base sur les caractères

Avant de pouvoir censurer un mot, nous allons créer des fonctions utilitaires qui serviront ensuite.

:::{admonition} Remarque
Dans ce TP, nous allons **réimplémenter à la main** certaines fonctions de traitement de texte (la conversion en minuscule ou la détection de lettres), **à titre pédagogique**.

Cela permet de comprendre comment ces opérations fonctionnent en interne et de s'entraîner à construire des fonctions simples.  

Ces fonctions ne traitent pas le cas où le texte contient des accents.

En situation réelle, on utiliserait bien sûr les fonctions déjà disponibles dans la bibliothèque standard de Python (`car.isalpha(), car.lower()`).
:::



### Exercice 1 : Tester si un caractère est alphabétique

Complétez la fonction `est_alphabétique`.

Objectif :
Renvoyer `True` si un caractère est une lettre (A–Z ou a–z).
Renvoyer `False` sinon.


:::{admonition} Indication
:class: tip dropdown

Vous pouvez utiliser des comparaisons comme : 'a' <= car <= 'z'
:::

```{code-cell} ipython3
---
nbgrader:
  grade: false
  grade_id: cell-26599ba8b0db5d2c
  locked: false
  schema_version: 3
  solution: true
---
def est_alphabétique(car):
    """
    Teste si le caractère car est alphabétique.
      Paramètre car : un caractère (string de longueur 1)
      Renvoie : True si car ∈ [A-Z], [a-z] ou [0-9], False sinon.
    """
    ### BEGIN SOLUTION
    return ('a' <= car <= 'z') or ('A' <= car <= 'Z')
    ### END SOLUTION
```

```{code-cell} ipython3
---
nbgrader:
  grade: true
  grade_id: cell-b141e2a8fe5b4d49
  locked: true
  points: 1
  schema_version: 3
  solution: false
---
# Tests
assert est_alphabétique('A') == True
assert est_alphabétique('z') == True
assert est_alphabétique('5') == False
assert est_alphabétique('.') == False
assert est_alphabétique(' ') == False
```

+++ {"nbgrader": {"grade": false, "grade_id": "cell-4034b50f9054165a", "locked": true, "schema_version": 3, "solution": false}}

### Exercice 2 : Mettre un caractère en minuscule

L'objectif de ce deuxième exercice est de transformer un caractère en lettre minuscule : si `car` est une majuscule, renvoyer la même lettre en minuscule, sinon, renvoyer `car` sans modification.


:::{admonition} Indication : ord() et chr()

Pour résoudre cet exercice, il est utile de comprendre deux fonctions Python permettant de manipuler les caractères :

- `ord(car)` : Renvoie le code numérique du caractère `car` (selon la table Unicode). Exemple : `ord('A') → 65`

- `chr(n)` : Renvoie le caractère correspondant au code numérique `n`. Exemple : `chr(65) → 'A'`

Pour les lettres majuscules et minuscules, les codes sont consécutifs :

'A' → 65

'B' → 66

...

'Z' → 90

Les minuscules sont 32 valeurs plus loin :

'a' → 97

'b' → 98

...

'z' → 122

Ainsi, pour transformer une majuscule en minuscule, on peut faire :

```python
chr(ord('A') + 32)   # donne 'a'

```

:::


Complétez la fonction `en_minuscule`.

```{code-cell} ipython3
---
nbgrader:
  grade: false
  grade_id: cell-248a410c27f82b9c
  locked: true
  schema_version: 3
  solution: false
---
def en_minuscule(car):
    """
    Renvoie la version minuscule d'un caractère si c'est une majuscule.
      Paramètre car : un caractère
      Renvoie : car en minuscule
    """
    ### BEGIN SOLUTION
    if 'A' <= car <= 'Z':
        return chr(ord(car) + 32)
    return car
    ### END SOLUTION
```

```{code-cell} ipython3
# Tests
assert en_minuscule('A') == 'a'
assert en_minuscule('Z') == 'z'
assert en_minuscule('a') == 'a'
assert en_minuscule('!') == '!'
```

+++ {"nbgrader": {"grade": false, "grade_id": "cell-b9ac4bd82bc4f381", "locked": true, "schema_version": 3, "solution": false}}

## Bilan de la partie 1

Vous savez maintenant :

- parcourir une chaîne ;

- reconnaître les caractères alphabétiques ;

- convertir un caractère majuscule en minuscule grâce à ord() et chr().

Dans la Partie 2, vous allez écrire une fonction qui vérifie si un mot apparaît à un endroit précis dans un texte.

```{code-cell} ipython3

```
