E02 - Ancien parchemin⚓︎
Le problème
Proposition 1⚓︎
🐍 Script Python
"""
Auteur : ********
https://prologin.org/train/2004/semifinal/ancien_parchemin
"""
def correspondance(nb_C_A, nb_C_P, texte_A, texte_P, indice_correspondance):
""" Renvoie l'indice de correspondance, si le texte de l'assistant peut correspondre au texte du parchemin trouvé
>>>correspondance(4, t?t?, 4, titi, 0)
1
>>>correspondance(11, kikoo lol ?, 11, Hello World, 0)
0
"""
if nb_C_A != nb_C_P:
return "0"
else:
for i in range(nb_C_P):
if texte_P[i] == "?":
pass
elif texte_A[i] == texte_P[i]:
indice_correspondance = 1
elif texte_A[i] != texte_P[i]:
indice_correspondance = 0
break
return indice_correspondance
import doctest
doctest.testmod
# Entrée
nb_caractère_parchemin = int(input())
texte_parchemin = input()
nb_caractère_assistant = int(input())
texte_assistant = input()
# Sortie
indice_correspondance = 0
print(correspondance(nb_caractère_assistant, nb_caractère_parchemin, texte_assistant, texte_parchemin, indice_correspondance))
- Erreurs sur doctest
Diff
- >>>correspondance(4, t?t?, 4, titi, 0)
+ >>> correspondance(4, "t?t?", 4, "titi", 0)
-
Avec Python, on préfère éviter de donner les longueurs des listes ou chaine ; c'est une habitude qui vient des vieux langages.
-
Tu pouvais utiliser un
return
à la place dubreak
. -
Tu pouvais ne pas utiliser
pass
. -
Il y a des lignes trop longues.
Proposition 2⚓︎
🐍 Script Python
def correspondance(nb_parchemin,texte,nb_assistant,texte_assistant):
if nb_parchemin == nb_assistant:
for i in range(nb_parchemin-1):
if texte[i] != "?":
if texte[i] != texte_assistant[i]:
return 0
else:
return 1
else:
return 0
nb_parchemin = int(input())
texte= input()
nb_assistant = int(input())
texte_assistant= input()
print(correspondance(nb_parchemin,texte,nb_assistant,texte_assistant))
import doctest
doctest.testmod()
- PEP-8 : De l'espace est souhaitée.
Diff
-correspondance(nb_parchemin,texte,nb_assistant,texte_assistant):
+correspondance(nb_parchemin, texte, nb_assistant, texte_assistant):
-
Mais aussi de meilleurs noms de variable.
-
Le
return 1
est mal placé, il est prématuré. Il faut tester toutes les lettres avant de renvoyer 1. Et on préfère renvoyerTrue
avec Python, on affichera1
dans la partie affichage.
Proposition 3⚓︎
🐍 Script Python
def vérification(parchemin_a_déchifré, parchemin_assistant, nb_chr_parchemin_a_déchifré):
"""renvoie 1 si le parchemin de l'assistant concide avec celui
a déchiffrer et 0 si il ne coincide pas
>>>4
>>>t?t?
>>>4
>>>titi
1
>>>11
>>>kikoo lol ?
>>>11
>>>hello world
0
"""
if nb_chr_parchemin_a_déchifré == nb_chr_parchemin_assistant:
for i in range(nb_chr_parchemin_a_déchifré):
if i+1 == nb_chr_parchemin_a_déchifré:
return 1
elif (parchemin_a_déchifré[i] != parchemin_assistant[i]
and parchemin_a_déchifré[i] != '?'):
return 0
else:
return 0
nb_chr_parchemin_a_déchifré = int(input())
parchemin_a_déchifré = list(input())
nb_chr_parchemin_assistant = int(input())
parchemin_assistant = list(input())
print(vérification(parchemin_a_déchifré, parchemin_assistant, nb_chr_parchemin_a_déchifré))
- C'est mieux de renvoyer un booléen,
True
ouFalse
, et ensuite d'afficher 0 ou 1 selon... Avec de vieux langages, comme le C, on aurait renvoyé, oui c'est vrai, 0 ou 1... Pas avec Python. - Revoir les doctests
- Ton test
if i+1 == nb_chr_parchemin_a_déchifré:
témoigne que tu sembles avoir copié une solution dans un autre language. Ceci est impossible en Python. - La fonction ne renvoie pas 1 dans tous les bons cas... Elle renvoie
None
à la fin de la boucle...
Proposition 4⚓︎
🐍 Script Python
def correspondance_parchemin(long_parchemin: int, parchemin: str, long_traduction: int, traduction: str) -> int:
"""
Renvoie 0 si la traduction apporté par l'assistant correspond au parchemin
>>> correspondance_parchemin(3, "a?c", 3, "abc")
1
>>> correspondance_parchemin(4, "a?cd", 5, "abcde")
0
"""
i = 0
if long_parchemin > long_traduction or long_traduction > long_parchemin: # pour vérifier si il ont les mêmes nombre de caractères
return 0
for lettre in parchemin:
if lettre == traduction[i] or lettre == "?":
i += 1
pass
else:
return 0
return 1
# Test
import doctest
doctest.testmod()
# Entrée
long_parchemin = int(input())
parchemin = input()
long_traduction = int(input())
traduction = input()
# Sortie
print(correspondance_parchemin(long_parchemin, parchemin,long_traduction, traduction))
- On peut tester directement si deux nombres sont différents avec
!=
- Le
i
était inutile. - Tu pouvais éviter le
pass
(comme presque toujours). - Renvoyer un booléen est mieux que 0 ou 1, habitude qui vient des vieux langages...
Proposition 5⚓︎
🐍 Script Python
def compare(liste1: list, liste2: list) -> bool:
"""
Cette fonction indique si les deux textes correspondent,
c'est à dire que tous les caractères visibles du texte du parchemin
(différents de '?') sont identiques aux caractères correspondants du texte de l'assistant.
>>> compare("t?t?","titi")
True
>>> compare("kikoo lol ?","hello world")
False
"""
if len(liste1) != len(liste2):
return False
for lettre1, lettre2 in zip(liste1, liste2):
if lettre1 != "?":
if lettre1 != lettre2:
return False
return True
# Entrée
import doctest
doctest.testmod()
nombre_caractères_texte_parchemin = int(input())
texte_parchemin = input()
nombre_caractères_texte_fourni_par_lassistant = int(input())
texte_assisant = input()
# Sortie
#print(1 if(compare(texte_parchemin, texte_assisant)) else 0)
#print(int(compare(texte_parchemin, texte_assisant)))
print(["0", "1"][compare(texte_parchemin, texte_assisant)])
- Presque parfait.
- Les identifiants pourraient être un peu meilleurs.
- L'annotation de type est fausse,
str
au lieu delist
. - Des trois possibilités de sortie que tu proposes, la dernière est la pire, il y a un transtypage implicite de
compare(...)
qui est un booléen vers un indice attendu entier. INTERDIT en NSI ! Et c'est mal ! La meilleure solution est la première ; tout le monde peut la comprendre. La seconde est acceptable.
Proposition 6⚓︎
🐍 Script Python
def Ancien_parchemin(nb_caractre_parchemin, text_parchemin, text_assistante):
"""
Renvoie True ou False, si les caractere du parchemin corsepond ou pas avec celui de l'assitance
"""
if text_parchemin[0] == text_assistante[0] or text_parchemin[0] == '?':
if nb_caractre_parchemin == 1:
return True
else:
return Ancien_parchemin(nb_caractre_parchemin-1, text_parchemin[1:], text_assistante[1:])
else:
return False
#Entrée
nb_caractre_parchemin = int(input())
text_parchemin = input()
nb_caractre_text = int(input())
text_assistante = input()
#Sortie
if nb_caractre_text != nb_caractre_parchemin:
print('0')
else:
print('1' if Ancien_parchemin(nb_caractre_parchemin, text_parchemin, text_assistante) == True else '0')
- Ne fonctionne pas avec des textes vides au départ, ils coïncident pourtant !!!
== True
est inutile. Le testif truc == True:
est équivalent àif truc:
.- Sinon, très jolie récursive.
Proposition 7⚓︎
🐍 Script Python
lettres_en_commun = 0
def valabilité_déduction():
"""Renverra :
-> 0 dans le cas où le texte de l'assistant de peut pas correspondre à celui du parchemin
-> 1 dans le cas où le texte de l'assistant peut correspondre à celui du parchemin
>>> 5
>>> av?i?
>>> 5
>>> avoir
1
>>> 8
>>> c?c?rico
>>> 8
>>> cocarico
0
>>> 9
>>> finland???
>>> 7
>>> finlande
0
"""
global lettres_en_commun
if nb_caractère_texte_parchemin != nb_caractère_déduction :
return 0
else :
for i in range(nb_caractère_déduction):
if texte_parchemin[i] == déduction[i] :
lettres_en_commun += 1
elif texte_parchemin[i] != déduction :
if texte_parchemin[i] == '?':
lettres_en_commun += 1
else : # si != de '?'
return 0
else :
return 0
if lettres_en_commun == nb_caractère_déduction :
return 1
nb_caractère_texte_parchemin, texte_parchemin, nb_caractère_déduction, déduction = int(input()), list(input()), int(input()), list(input())
print(valabilité_déduction())
- Avec Python, on préfère renvoyer des booléens plutôt que 0 ou 1, c'était une habitude avec de vieux langages...
- Inutile d'utiliser des variables globales ; ce n'est pas joli.
- il manque
[i]
audéduction
duelif
. - le dernier
else
est inutile ; cas impossible. - tu pouvais ne pas utiliser le nombre de caractères en commun...
- revoir le doctest.
Corrigé du professeur⚓︎
🐍 Script Python
"""
author: Franck CHAMBON
problem: https://prologin.org/train/2004/semifinal/ancien_parchemin
"""
def correspond(texte_1: str, texte_2: str) -> bool:
"""texte_1 et texte_2 correspondent-ils ?
>>> correspond("t?t?", "titi")
True
>>> correspond("kikoo lol ?", "hello world")
False
"""
l_1 = len(texte_1)
l_2 = len(texte_2)
if l_1 != l_2:
return False
else:
for c_1, c_2 in zip(texte_1, texte_2):
if c_1 != '?':
if c_1 != c_2:
return False
return True
# Tests
import doctest
doctest.testmod()
# Entrée
l_1 = int(input())
texte_1 = input() # le parchemin
assert l_1 == len(texte_1)
l_2 = int(input())
texte_2 = input() # le texte de l'assistant
assert l_2 == len(texte_2)
# Sortie
print("1" if correspond(texte_1, texte_2) else "0")
Remarques
Le bout de code
🐍 Script Python
if c_1 != '?':
if c_1 != c_2:
return False
aurait pu s'écrire
🐍 Script Python
if (c_1 != '?') and (c_1 != c_2):
return False
mais ici la première version semble plus limpide à comprendre. On préfèrera souvent la seconde, dans d'autres situations.
zip
🐍 Script Python
for c_1, c_2 in zip(texte_1, texte_2):
...
pourrait être remplacé par :
🐍 Script Python
longueur_commune = min(l_1, l_2) # ici l_1 == l_2
for i in range(longueur_commune):
c_1 = texte_1[i]
c_2 = texte_2[i]
...