Aller au contenu

E04 - Initiales⚓︎

Le problème

Initiales

Proposition 1⚓︎

🐍 Script Python
import string
def initiales(nb_caractère: int, chaine_caractère: str) -> str:
    """Cette fonction prend en paramètre une chaine de caractère et affiche la première lettre de chacun de ces mots en majuscule.
    >>> 21
        rentre avec tes pieds
    RATP
    """
    chaine_finale = []
    string.capwords(chaine_caractère)
    for x in range(nb_caractère-1):
        if chaine_caractère[x] == " ":
            pass
        else:
            if chaine_caractère[x] == chaine_caractère[x].upper():
                chaine_finale.append(chaine_caractère[x])
            else:
                pass
    return chaine_finale
# tests
import doctest
doctest.testmod()

# Entrée
nb_caractère = int(input())
chaine_caractère = input()

# Sortie
print(initiales(nb_caractère, chaine_caractère))
  • Le import string annonce une forme de triche avec capwords ; ce n'est pas l'esprit du problème.
  • Le doctest est à revoir.
  • Les else pass sont à supprimer.
    • Le premier en inversant le test.
  • Le capwords est utilisé... mais le résultat non sauvegardé, donc inutilisé.
  • split n'est pas utilisé, c'est bien, mais
  • le programme échoue, revoir l'algorithme.

Proposition 2⚓︎

🐍 Script Python
def initiales(chaine_caractère : str) -> str:
    """ Renvoie les Initiales d'une chaine de caractère
    >>> initiales("oui bonjour")
    'OB'
    >>> initiales("je suis pas là")
    'JSPL'
    """
    liste_chaine = list(chaine_caractère.split())
    initiale = ""

    for x in range(len(liste_chaine)):
        initiale += liste_chaine[x][0].upper()

    return initiale

# tests
import doctest
doctest.testmod()

# Entrée
nb_caractères = int(input())
chaine_caractère = input()
# Sortie
print(initiales(chaine_caractère))
  • Aérer le doctest.
  • Ne pas utiliser split est mieux sur ce problème, c'est comme tricher.
  • Il vaut mieux accumuler les initiales dans une liste, et les coller à la fin avec "".join(...). Pourquoi ?
    • Accumuler dans une nouvelle chaine (immuable) conduit à calculer un nouveau hash à chaque tour, et donc une complexité quadratique.
    • Accumuler dans une liste (muable) ne provoque pas de calcul de hash. On reste en linéaire. Le join final reste linéaire. C'est la bonne méthode.

Quand on doit accumuler des objets, il faut penser en premier à une liste !

Proposition 3⚓︎

🐍 Script Python
nombre_caractères = int(input())
liste_mots = list(input().split(" "))

initiales_majuscules = "".join(mot[0].upper() for mot in liste_mots)

print(initiales_majuscules)
  • On attend une fonction avec doctest,
  • et sans utiliser split ici...

Proposition 4⚓︎

🐍 Script Python
def initiales(texte):
  """Renvoie l'initiale de chaque mots de la phrase.
  >>> initiales('Rentre Avec tes pieds')
  RATP
  """ 
  lettre=""
  for i, c in enumerate(texte):
    if c!=" " and (i==0 or (i > 0 and texte[i-1] == " ")):
      lettre += c.upper()
  print(lettre)

# Test
import doctest
doctest.testmod()

# Entrées  
nb_lettre = int(input())
texte=input()

# Sortie
initiales(texte)
  • Très bien, il n'y a pas le split.
  • Aérer le doctest.
  • Bon algorithme.

Proposition 5⚓︎

🐍 Script Python
def cherche_initiales(liste_phrase):
    """ cherche les initieles d'une phrase est l'affiche
    >>>cherche_initiales(['rentre', 'avec', 'tes', 'pieds'])
    RATP
    """
    initiale = []
    for x in liste_phrase:
        initiale.append(x[0].upper())
    return initiale

""" mon doctest ne marche pas 
import doctest
doctest.testmod()    
"""
nb_lettre = int(input())
liste_phrase = input().split()

print("".join(cherche_initiales(liste_phrase)))
  • >>>cherche_initiales([ : erreur
  • >>> cherche_initiales([ : OK
  • On préfère une fonction qui prend les paramètres d'origine du problème, mais pas une liste. On veut les initiales d'une phrase, alors le paramètre est la phrase.

Proposition 6⚓︎

🐍 Script Python
def première_lettre(phrase):
    """ Cette fonction prend en paramètre une chaine de caractères, et affiche la première lettre de chacun de ces mots, en majuscule.

    Je n'ai pas activer le test, car celui-ci faisait bugger le programme et je ne sais pas comment le rendre juste.
    #>>> première_lettre(rentre avec tes pieds)
    RATP

    """
    for lettre in liste:
        print(lettre[0].upper(), end="")

# tests
import doctest
doctest.testmod()

# Entrée
nb_caractères = int(input())  #cette variable n'a pas d'action dans le programme, elle est "passive".
phrase = input()
liste = phrase.split() 

# Sortie
première_lettre(phrase)
  • >>> première_lettre(rentre avec tes pieds) : erreur
  • >>> première_lettre("rentre avec tes pieds") : correct
  • On préfère une version sans split...

Proposition 7⚓︎

🐍 Script Python
# 0- Coeur du programme

def construire_initiales(nb_lettres: int, chaine_mots: list) -> str:
    """ Renvoie la première lettre de chacun des mots de chaine_mots
    >>> construire_initiales(11, ["Hello","World"])
    'HW'
    >>> construire_initiales(21, ["rentre", "avec", "tes", "pieds"])
    'RATP'
    """

    initiales = ""
    for mot in chaine_mots:
        initiales += mot[0].upper()
    return initiales

# 1- Tests

import doctest
doctest.testmod()

# 2- Lecture des entrées

nb_lettres = int(input())
chaine_mots = input().split()

# 3- Appel de la fonction / Sortie

print(construire_initiales(nb_lettres, chaine_mots))
  • Au lieu de passer une liste en paramètre, il vaut mieux la chaine.
    • C'est plus cohérent avec la longueur donnée aussi en paramètre.
  • Et on préfère une version sans split.

Proposition 8⚓︎

🐍 Script Python
def initiales(texte : str) -> str :
    """ Renvoie la première lettre de chaque mot, en majuscule, dans la chaine de caractère 'texte'.

    >>> texte = 'rentre avec tes pieds'
    >>> initiales(texte)
    RATP

    """
    for mot in texte :
        print(mot[0].upper(), end="") #mot[0] = initiale 

# tests
import doctest
doctest.testmod()

# Entrée
nb_caracteres = int(input())
assert 1 <= nb_caracteres <= 200
texte = input().split()

# Sortie
initiales(texte)
  • Bon doctest.
  • Bon commentaire, mais on préfère
    • le remplacer par : initiale = mot[0],
    • puis utiliser print(initiale.upper(), end="")
  • assert inutile ici...
  • On préfère une fonction qui renvoie les initiales plutôt que son affichage.
  • L'annotation de type est incorrecte ici,
    • la fonction renvoie None,
    • texte n'est pas de type str, mais de type list.

Corrigé du professeur⚓︎

🐍 Script Python
"""
author: Franck CHAMBON
problem: https://prologin.org/train/2003/semifinal/initiales
"""

def majuscule(lettre: str) -> str:
    """Renvoie la version majuscule de `lettre`,
    `lettre` est donnée en minuscule.

    >>> majuscule('r')
    'R'

    """
    id_lettre = ord(lettre) - ord('a')
    lettre_maj = chr(ord('A') + id_lettre)
    return lettre_maj


def initiales(chaine: str) -> str:
    """Renvoie les initiales de la chaine, en majuscules.

    >>> initiales("rentre avec tes pieds")
    'RATP'

    """

    taille = len(chaine)
    if taille == 0: # ce cas ne devrait pas se produire
        return ""
    if chaine[0] == " ":
        sigle = []
    else:
        sigle = [majuscule(chaine[0])]
    for i in range(1, taille):
        if (chaine[i - 1] == ' ') and (chaine[i] != ' '):
            sigle.append(majuscule(chaine[i]))
    return "".join(sigle)


import doctest
doctest.testmod()

taille = int(input())
chaine = input()

print(initiales(chaine))
  • On n'a pas utilisé ni split, ni upper.
  • Chaque fonction a son doctest.
  • La fonction prend en compte le cas où la chaine commence par une espace.
  • On utilise le fait que l'entrée est en minuscule !

Une version fonctionnelle serait

🐍 Script Python
def initiales(chaine: str) -> str:
    return "".join(mot[0].upper() for mot in chaine.split())