Aller au contenu

E05 - Nétiquette⚓︎

Le problème

Nétiquette

Proposition 1⚓︎

🐍 Script Python
def retour_ligne(nb_caracteres,caracteres):
    i=0
    retour_car=''
    car_test=''
    while i<nb_caracteres:
        car_test = caracteres[i:81+i]
        if len(car_test)>80:
            x = car_test.rfind(' ')
            retour_car = retour_car + car_test[0:x] + '\n'
            i=i+x+1
        else:
            retour_car=retour_car+car_test
            i=nb_caracteres+1
    return retour_car

nb_c=int(input())
car=input()
print(retour_ligne(nb_c,car))

import doctest
doctest.testmod()
  • utiliser rfind c'est un peu tricher... (beaucoup)
  • La fonction est bien trop obscure !!!

Proposition 2⚓︎

🐍 Script Python
def arrangement(nb_caractères: int, texte: str, compte: int)-> None:
    """ Écrit au fur à mesure, le texte en sautant une ligne
    tout les 80 caractères sans couper les mots en deux.

    >>> 217
    >>> Prologin est le concours national d'informatique. Prologin selectionne egalement l'equipe de France pour les Olympiades Internationales d'Informatique, evenement qui reunit 80 pays dans un lieu different chaque annee.
    >>> arrangement(nb_caractères, texte)

    Prologin est le concours national d'informatique. Prologin selectionne egalement
    l'equipe de France pour les Olympiades Internationales d'Informatique, evenement
    qui reunit 80 pays dans un lieu different chaque annee.

    """

    for mot in texte:
        compte += len(mot)
        if compte >= 80:
            print()
            compte = 0
        else:
            print(" ",end="")
        print(mot, end="")

# Test (C'est en commentaire car il ne passe pas les test :\)
# import doctest
# doctest.testmod()

# Entrée
nb_caractères = int(input())
texte = list(input().split(" "))

# Sortie
compte = 0
arrangement(nb_caractères, texte, compte)
  • C'est la longueur des mots avec espace qui doit être inférieur à 80, toi tu as oublié de compter les espaces.

  • On peut réparer ta fonction avec

🐍 Script Python
    compte = 0
    for mot in texte:
        if compte == 0:
            # on débute la première ligne
            print(mot, end="")
            compte = len(mot)
        elif compte + 1 + len(mot) <= 80:
                print(" ", mot, sep="", end="")
                compte += 1 + len(mot)
        else:
            print()
            print(mot, end="")
            compte = len(mot)

Ça reste peu pratique.

Proposition 3⚓︎

🐍 Script Python
def Netiquette(string, longueur):
    """
    Prend en paramètre une chaine de caractère, et la transforme de sorte à
    ce qu'elle respecte la Netiquette (80 chr par ligne)
    Ou en tout cas, ça essaye. Ca râte misérablement, car je ne sais pas comment vérifier sur chaque mot.
    Ca respecte la Netiquette, mais ne respecte pas les espaces.

    >>> Netiquette(Prologin est le concours national d'informatique. Prologin selectionne egalement l'equipe de France pour les Olympiades Internationales d'Informatique, evenement qui reunit 80 pays dans un lieu different chaque annee.)
    'Prologin est le concours national d'informatique. Prologin selectionne egalement
    l'equipe de France pour les Olympiades Internationales d'Informatique, evenement
    qui reunit 80 pays dans un lieu different chaque annee.'
    """
    nouvelle_string = ""
    for i, lettre in enumerate(string):
        if i % 80 == 0:
            nouvelle_string += '\n'
        nouvelle_string += string[i]
    return nouvelle_string[1:]


#input
_ = int(input())
texte = input()


#output
print(Netiquette(texte, _))
  • Tu n'utilises pas le second paramètre ; ne l'inclus donc pas dans les paramètres !
  • Ton code est incorrect, il coupe les mots. On veut que les mots ne soient pas coupés, il faut couper aux espaces... Ceux juste avant de dépasser la ligne de 80...
  • C'est une très mauvaise pratique d'accumuler des lettres dans une chaine de caractères. On préfère accumuler dans une liste (ou une file), puis faire un collage "".join(...)

Proposition 4⚓︎

🐍 Script Python
def Nétiquette(chaine: str, long_chaine: int) -> str:
    """
    Affiche une chaine avec la norme "Nétiquette" qui consiste a ce que les ligne de dépasse pas 80 caractères.

    >>> Nétiquette("Prologin est le concours national d'informatique. Prologin selectionne egalement l'equipe", 90)
    Prologin est le concours national d'informatique. Prologin selectionne egalement
    l'equipe

    """
    compteur = 80
    while compteur <= long_chaine:
        if chaine[compteur] == " ":
            print(chaine[:compteur])
            chaine = chaine[compteur + 1:]
            compteur = 80
            long_chaine = len(chaine) - 1
        else:
            compteur -= 1
    print(chaine)


# Test

import doctest
doctest.testmod()

# Entrée

long_chaine = int(input())
chaine = input()

# Sortie

Nétiquette(chaine, long_chaine)
  • Méthode intéressante, mais elle pourrait échouer à cause de long_chaine = len(chaine) - 1 ; le -1 étant faux dans de rares cas.

Proposition 5⚓︎

🐍 Script Python
def netiquette(texte: str) -> str:
    """
    Renvoie une chaine de caractere dont certains espaces ont été remplacé par 
    des sauts de ligne ('\n') de telle sorte qu'aucune ligne ne dépasse 80 
    colonnes.

    """
    if len(texte) <= 80:
        return texte
    else:
        i_cesure = 80
        while texte[i_cesure] != " ":
            i_cesure -= 1
        return texte[:i_cesure] + '\n' + netiquette(texte[i_cesure + 1:])


import doctest
doctest.testmod()

nb_caracteres = int(input())
texte = input()

print(netiquette(texte))
  • Presque parfait.

  • Tu pouvais juste ajouter un paramètre par défaut sur la largeur de césure, et donner un doctest complet qui fait moins de 80 de large.

    • Pour le doctest, c'est légal de faire :
🐍 Script Python
"""

>>> texte = "Un exemple court."
>>> print(netiquette(texte), 15)
Un exemple
court.

"""

Cela t'évite d'écrire des \n dans la docstring.

Corrigé du professeur⚓︎

On remarque qu'une version récursive est bien plus simple à écrire et à comprendre qu'une version itérative. Mais, quand c'est presque aussi facile à écrire et comprendre, on préfère les versions itératives.

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

def netiquette(texte: str, largeur=80) -> str:
    """Renvoie le texte formaté sur plusieurs lignes,
    avec une largeur maximale définie, 80 par défaut.

    >>> print(netiquette("123 12 1", largeur=4))
    123
    12 1

    """
    l_texte = len(texte)
    if l_texte <= largeur:
        return texte
    else:
        # On cherche l'indice de la première espace à gauche de largeur.
        i = largeur
        while texte[i] != ' ':
            i -= 1
        return texte[:i] + "\n" + netiquette(texte[i+1:], largeur)

# Tests
import doctest
doctest.testmod()

# Entrée
longueur = int(input())
texte = input()
assert longueur == len(texte)

# Sortie
print(netiquette(texte))

doctest facile

Il est utile ici de choisir un paramètre supplémentaire, la longueur maximale autorisée. Cela permet de pouvoir ajouter un doctest de taille raisonnable.

On peut utiliser print dans le doctest !

pré-condition

Quand on rentre dans la boucle while, au maximum i = largeur et texte[i] ne provoque pas d'erreur, en effet, juste avant on vient de tester et on est dans le cas largeur < l_texte.

D'autre part, i ne peut pas devenir nul, il y aurait un mot trop long.