J'essaie de faire une fonction qui permet de savoir si un automate est deterministe ou non.
Seulement je suis bloqué pour la condition du : au maximum une fleche d'un caractère sortant d'un état.
J'ai donc fait cette fonction :
def auto_det(nb)
fichier = open('automate.txt', 'r')
for i in range(0, nb+1):
ligne1 = fichier.readline()
l1 = list(ligne1)
print(l1)
l1.pop()
"""for j in range(0,nb+1):
ligne2 = fichier.readline()
l2 = list(ligne2)
l2.pop()
if(l2[1] == l2[1]):
print("l'automate à un doublons de libellé")"""
Pour faire simple : 1- je veux lire dans le fichier les transitions (exemple : 3a5) ; 2 transformer cette ligne en liste; 3 supprimer le dernier élément de cette liste (car je ne compare que les deux premiers éléments)
Je fais ça pour la ligne courante et la suivante. Mais j'ai un problème, apparemment la liste l1 (et l2 mais le programme n'arrive pas à cette étape) est vide. Pourtant la fonction lit bien les lignes.
Mais j'ai un problème, apparemment la liste l1 (et l2 mais le programme n'arrive pas à cette étape) est vide. Pourtant la fonction lit bien les lignes.
Python ne se trompe pas: si la liste est vide, c'est que la chaine de caractères est vide, donc que readline() a retourné une chaine de caractères vide...
Or si readline retourne une ligne, une ligne vide n'est jamais une chaine vide: elle contiendra au moins '\n' disant fin de ligne.
chaine vide est un retour particulier de readline qui signale juste qu'il n'y plus rien à lire.
Tout ce qu'on peut dire c'est que le fichier contient un nombre de lignes inférieur à nb.
Après, est ce que le fichier est supposé contenir nb lignes et si on en trouve moins ben... c'est pas un fichier "intègre" et il faut traiter l'erreur ou est-ce que vous avez écrit cette boucle un peu au hasard et qu'il faudrait revoir un peu tout çà?
Mais j'ai un problème, apparemment la liste l1 (et l2 mais le programme n'arrive pas à cette étape) est vide. Pourtant la fonction lit bien les lignes.
Python ne se trompe pas: si la liste est vide, c'est que la chaine de caractères est vide, donc que readline() a retourné une chaine de caractères vide...
Or si readline retourne une ligne, une ligne vide n'est jamais une chaine vide: elle contiendra au moins '\n' disant fin de ligne.
chaine vide est un retour particulier de readline qui signale juste qu'il n'y plus rien à lire.
Tout ce qu'on peut dire c'est que le fichier contient un nombre de lignes inférieur à nb.
Après, est ce que le fichier est supposé contenir nb lignes et si on en trouve moins ben... c'est pas un fichier "intègre" et il faut traiter l'erreur ou est-ce que vous avez écrit cette boucle un peu au hasard et qu'il faudrait revoir un peu tout çà?
Merci à tous les deux pour vos réponses, en effet après avoir longuement deboggé, le problème venait du faire que le programme lisait une ligne +1 et donc la liste devenait vide. J'ai donc réduire la boucle de 0 à nb et le problème est réglé.
Par hasard, comme ce problème ne vient pas tout seul :D, je voulais savoir, comme dit plus haut, je souhaite comparé les deux premiers elements de deux listes differentes (où les listes seraient la ligne actuellement lu et la ligne suivante).D'où la double boucle. j'ai donc tenté ceci :
for i in range(0, nb):
ligne1 = fichier.readline()
l1 = list(ligne1)
print(l1)
l1.pop()
for j in range(0,nb):
ligne2 = fichier.readline()
l2 = list(ligne2)
l2.pop()
if(l1[0] and l1[1] == l2[0] and l2[1]):
print("l'automate à un doublons de libellé")
Or je veux commencer les opérations à partir d'une certaine ligne et non sur tout le fichier.
Mais j'ai en erreur un out of range. dans le if. Auriez vous des pistes ?
Pourquoi faire une boucle pour juste aller lire la ligne suivante?
Le code doit refléter ce que vous voulez faire. Si vous dites "je veux commencer les opérations à partir d'une certaine ligne", çà veut dire qu'on va lire des lignes en les ignorant ou tant qu'on n'y trouve pas une certaine condition... puis on passe à l'étape suivante.
Si dans le code on ne trouve rien qui traduise l'intention de départ, çà ne marchera pas.
Ce que vous pouvez constater à l'exécution. Vous auriez pu le constater déjà en essayant de relire le code tout en imaginant ce que la machine allait bien pouvoir en faire.
Pourquoi faire une boucle pour juste aller lire la ligne suivante?
Le code doit refléter ce que vous voulez faire. Si vous dites "je veux commencer les opérations à partir d'une certaine ligne", çà veut dire qu'on va lire des lignes en les ignorant ou tant qu'on n'y trouve pas une certaine condition... puis on passe à l'étape suivante.
Si dans le code on ne trouve rien qui traduise l'intention de départ, çà ne marchera pas.
Ce que vous pouvez constater à l'exécution. Vous auriez pu le constater déjà en essayant de relire le code tout en imaginant ce que la machine allait bien pouvoir en faire.
ha !
je me disais que faire deux boucles étaient bons. Le problèm est que je ne vois pas comment faire pour faire en sorte de commencer à une certaine ligne.
Je comptais comparer deux listes donc deux boucles pour savoir si elles étaient identiques par cette méthode
je me disais que faire deux boucles étaient bons. Le problèm est que je ne vois pas comment faire pour faire en sorte de commencer à une certaine ligne.
C'est un fichier texte. Les lignes sont à priori de longueur variable. Et si on veut dire j'ignore tout ce qui est avant la 10ième ligne, il faut lire 9 lignes en ignorant leur contenu... puis arrivé là, on va pouvoir passer aux choses sérieuses.
Kidorich a écrit:
Je comptais comparer deux listes donc deux boucles pour savoir si elles étaient identiques par cette méthode
Séparez les difficultés: avant de comparer vos listes, il faut lire le fichier pour y récupérer ce qui permettra de construire les listes. Et lire un fichier texte, c'est déjà une boucle qui va produire les listes à comparer. Tant que ce boulot là n'est pas fait, pas de listes et à fortiori pas de listes à comparer.
A la sortie de cette boucle là, par contre, on devrait avoir 2 listes.
Comment les comparer sera l'étape suivante... Et si çà fait du sens de le faire avec une boucle ou des boucles imbriquées pourquoi pas mais çà ne change pas le boulot à faire avant.
Ce qui m'agace est la ligne suivante: if(l1[0] and l1[1] == l2[0] and l2[1]): Ça laisse supposer qu'il y a des booléens ou des 0 et des 1 dans ces éléments. Je ne crois pas que c'est ça qui s'y trouve. Il faudra revoir ce test. Pourquoi l1[0] et l1[1]? Revises ce que mps a écrit.
Le Tout est souvent plus grand que la somme de ses parties.
Après avoir lu vos messages, vos conseils, j''ai repris "à zéro" ma (mes) fonction(s) en les découpant en sous problème.
Voici ce que j'ai fait :
j'ai donc découper ma grosse fonction en sous fonctions afin de recuperer les resultats de ces sous fonctions.
1 qui va recuperer les deux premieres transiitions uniquement (car si deux transitions avec le meme caractère : non deterministe)
1 qui va transformer les deux premieres transitions (ligne du fichier) en liste et enlever le dernier élément et cela pour la ligne courante et la ligne suivante
1 qui va pouvoir comparer le premier et deuxieme élément et donc dire s'ils dans les deux listes ce sont les meme. SI oui ==> doublons = 1 sinon doublons = 0
1 qui prend le nb d'entree et le doublon
Le problème est lors de la comparaison, j'ai un out of range et j'ai repensé au truc du binaire mais je comprends toujours pas.
Je pense ne pas être loin.
Voici le code :
def recup_transitions(nb):
fichier = open('automate.txt', 'r')
for i in range(0,nb):
ligne = fichier.readline()
if(i==3):
l1 = etat_entree_et_transition(ligne) #liste de la ligne courante
ligne_suivante = fichier.readline()
ligne_suivante = etat_entree_et_transition(ligne_suivante)
l2 = ligne_suivante
l_entree = [l1,l2]
return l_entree
def etat_entree_et_transition(ligne):
liste_etats = list(ligne)
liste_etats.pop()
return liste_etats
def check_libelle_transition(liste_etats):
temp1 = liste_etats[0]
temp2 = liste_etats[1]
if temp1[0] == temp2[0]:
pass
if temp1[1] == temp2[1]:
#il y a un doublon de libellé
doublon = 1
return doublon
else :
doublon = 0
return 0
return 0
def est_un_automate_deterministe(nb_entree, doublon):
if(nb_entree == 0):
print("l'automate n'existe pas")
elif(nb_entree == 1):
print("l'automate n'est pas deterministe")
elif(nb_entree == 2 and doublon == 0):
print("l'automate à une entrée et un libellé unique\n")
print("L'automate est deterministe")
Dans ton premier message, tu disais que les lignes ont l'allure suivante: 3a5 Est-ce bien correct? Puis tu veux transformer en une liste: [3, 5] Et faire un pop du dernier? Donne des exemples de lignes complètes. On ne connais pas la valeur de nb passée en paramètre. Je n'aime pas l'idée de lire une ligne et la suivante. La suivante existe-t-elle toujours? Peux-tu donner le TraceBack complet pour qu'on sache où ça bloque? Je soupçonne que c'est dans le pop() mais ...
Le Tout est souvent plus grand que la somme de ses parties.
Les lignes ont bien l'allure 3a5. Non , je veux transformer la liste en ["3","a"], donc oui je veux faire un pop du dernier element.
une ligne complete dans le fichier : 0a1.
Nb est le nombre de ligne du fichier (retourner dans une autre fonction). Dans le fichier automate.txt il est de 15.
Dans le fichier les transitions commencent à la ligne 5 (erreur dans mon code lors de la condition if dans recup_transition). Les lignes suivantres sont les autres transitions.
Oui après test la ligne suivante est bien lue. et j'ai aussi remarqué que je dois pop() deux fois car le retour à la ligne st presente dans la liste.
Voici le traceback :
Traceback (most recent call last):
File "d:\GitHub\Projet-math-info-\main.py", line 21, in <module>
main()
File "d:\GitHub\Projet-math-info-\main.py", line 14, in main
doublon = check_libelle_transition(liste_etats)
File "d:\GitHub\Projet-math-info-\fonctions.py", line 61, in check_libelle_transition
temp2 = liste_etats[1]
IndexError: list index out of range
L'erreur dit juste que liste_etats ne contient pas le nombre d'items attendus.
Affichez les lignes et le contenu des listes pour avoir une idée du problème:
def recup_transitions(nb):
fichier = open('automate.txt', 'r')
for i in range(0,4):
ligne = fichier.readline()
l1 = etat_entree_et_transition(ligne) #liste de la ligne courante
print(ligne, l1)
ligne = fichier.readline()
l2 = etat_entree_et_transition(ligne_suivante)
print(ligne, l2)
l_entree = [l1,l2]
return l_entree
J'ai fait un copier-coller deton code sans le main que je n'avais pas. Je suis sur Windows 10, je travaille avec cmd et j'édite avec notepad (Block-Notes) Si je fais un print(ord(ligne_suivante[-1])), j'obtiens 54 qui est le code d'un '6' qui se trouvait bien dans mon fichier automate.txt Le code du '\n' aurait été 10. Tu n'as pas besoin de faire un pop() pour l'enlever. Comme l'a suggéré mps, fait des print un peu partout pour suivre la progression. Il y a beaucoup de choses bizarres dans ton code. Par exemple, '3a6' devient ['3', 'a', '6'] après le list() et ['3', 'a'] après le pop() l_entree = [l1,l2] return l_entree Tu peux faire directement return [l1, l2] Puisque tu ne sembles pas avoir beaucoup de lignes dans ton fichier automate.txt et qu'elles sont assez courtes, je les aurais toutes lues sans me fier au nb et je les aurais placées dans une liste de str. J'aurais vérifié que le nombre de lignes était suffisant et j'aurais pris les lignes qui m'intéressent. Je te rappelle que les nombres sont en format str et non int. Si tu veux faire des calculs, tu devras les convertir.
Le Tout est souvent plus grand que la somme de ses parties.
Oui c'est normal qu'il ne reste que quelque chose de la forme ['3', 'a' ]
UPDATE : après avoir vérifier la fonction de récup des transitions , les différents print m'ont permis de voir que c'est correct, que ça fonctionne (après légère modif) et que le problème se situe plus sur la fonction check_libelle_transition. Je revois ça.
REUPDATE
Bon.. j'ai revu les fonctions et il s'avère que la fonction check est bizarre. La liste de liste que je crée dans recup_transistions est bien là mais dés qu'il faut passer la liste dans etat_entree_et_transition ça ne fonctionne pas. PIRE, j'ai print pour voir, elle est vide alors que dans recup_transition elle est bonne...
Là je ne sais vraiment pas pourquoi..
def recup_transitions(nb):
fichier = open('automate.txt', 'r')
liste_etats = []
for i in range(0,nb):
ligne_courante = fichier.readline()
if(i==5):
ligne_courante = etat_entree_et_transition(ligne_courante)
print(ligne_courante)
liste_etats.append(ligne_courante)
ligne_suivante = fichier.readline()
ligne_suivante = etat_entree_et_transition(ligne_suivante)
liste_etats.append(ligne_suivante)
print("liste après ope : ", liste_etats)
return liste_etats
def etat_entree_et_transition(ligne):
i = 0
ligne = list(ligne)
print(ligne)
while(i<=1):
ligne.pop()
i = i+1
return ligne
def check_libelle_transition(liste_etats):
print("liste recu apres op", liste_etats)
l1 = liste_etats[0]
l2 = liste_etats[1]
return 0
if l1[0] == l2[0]:
pass
if l1[1] == l2[1]:
#il y a un doublon de libellé
doublon = 1
return doublon
else :
doublon = 0
return doublon
Tu peux simplifier si tu ne fais qu'un pop() def etat_entree_et_transition(ligne): return list(ligne)[:-1] Pour la fin de ligne, je crois que tu avais raison, il y a bien un '\n' à la fin. Je n'avais que 4 lignes dans mon fichier automate.txt et la dernière n'avait pas de fin de ligne. Qu'il y en ait une ou pas, tu peux faire: ligne = ligne.replace('\n', '') Tu le fais pour les deux lignes juste après la lecture.
Le Tout est souvent plus grand que la somme de ses parties.
S'il le ligne juste avant l'appel de la fonction n'est pas le même que le ligne reçu en paramètre, c'est qu'il s'est passé des choses entre les 2 ou que vous avez mal regardé. Et pour le coup sans code qui permette de reproduire quoi que ce soit, pas facile d'imaginer quelque chose qu'il faut voir pour y croire.
J'ai eu un peu de difficulté à comprendre. Dans mon code, j'ai fait ce que humfred a dit. J'ai appelé les fonctions à la suite dans le main. J'ai déjà mentionné qu'effectivement, il y a une fin de ligne qu'il faut enlever. Je précise comment. Je crois que Kidorich ne comprend pas lui-même ce qu'il doit faire. On se retrouve avec des listes du genre: [['4', 'a'], ['3', 'a']] À quoi servent les 'a' ? J'aurais vu séparer la ligne comme suit: '1a3' -> ['1', '3'] La fonction check aurait deux nombres à comparer. Il suffit de faire un ligne.split('a') après avoir enlevé la fin de ligne ('\n')
Le Tout est souvent plus grand que la somme de ses parties.
c'est vrai que ça semble plus logique d'avoir des chiffres (en espérant qu'il n'y ai pas de nombres en fait) à comparer mais bon, c'est lui le sachant du pourquoi
On peut avoir simplement: def etat_entree_et_transition(ligne): ligne = ligne.replace('\n', '') ligne = ligne.replace(' ', '') # si requis return ligne.split('a') t
Le Tout est souvent plus grand que la somme de ses parties.
Après divers tentative j'ai trouvé un autre moyen de faire ce que je voulais faire, à savoir récupérer la ligne et la transformer en liste. J'ai finalement trouver une autre méthode qui me permet de raccourcir et d'éviter ainsi les problèmes "d'algorithmie".
Pour vous répondre, le 'a' dans la ligne est le caractère de transition de l'automate. Il est nécessaire pour ma fonction. Le seul caractère inutile est le troisième.
Voici le code "réparer" :
def recup_transitions(nb):
fichier = open('automate.txt', 'r')
liste_etats = []
for i in range(0,nb):
ligne_courante = fichier.readline()
if(i==5):
ligne_courante = ligne_courante.replace("\n", "")
print(ligne_courante)
ligne_courante = etat_entree_et_transition(ligne_courante)
ligne_suivante = fichier.readline()
print(ligne_suivante)
ligne_suivante = ligne_suivante.replace("\n", "")
ligne_suivante = etat_entree_et_transition(ligne_suivante)
liste_etats.append(ligne_courante)
liste_etats.append(ligne_suivante)
print("liste après ope : ", liste_etats)
return liste_etats
def etat_entree_et_transition(ligne):
ligne = ligne[:-1]
return ligne
def check_libelle_transition(liste_etats):
print("liste recu apres op", liste_etats)
l1 = liste_etats[0]
l2 = liste_etats[1]
if(l1[0][0] == l2[1][0]):
print("il y a un doublon")
else:
print("ici")
tout est bon sauf la fonction check_libelle_transition, dans la laquelle je n'arrive pas à comparer les éléments de chaque liste. Voilà un aperçu du output que j'obtiens: .
Comme on peut le voir, la fonction ne passe même pas dans ma condition if. Comme une str est une liste en soit, je compare chaque caractère de str avec l'autre.
Dans ta fonction recup_transition, puisque tu n'as que 2 éléments dans liste_etats, tu peux faire directement: return [ligne_courante, ligne_suivante] Tu peux mettre les deux replace dans la fonction etat_entree_et_transition avant le slicing ligne[:-1] Ton code en sera d'autant simplifié. Si le 'a' est nécessaire, dois-je comprendre qu'il pourrait y avoir une autre lettre? Sinon ce serait inutile. Dans ta fonction check_libelle_transition, tu reçois une liste de 2 chaînes. Exemple: ['1a', '2a'] l1 vaut '1a', l1[0] vaut '1', mais que vaut l1[0][0] ? Tu dois reviser ce bout de code.
Le Tout est souvent plus grand que la somme de ses parties.
regarde ton test, tu compares l1[0][0] qui vaut '0' et l2[1][0] qi vaut 'a';
l1='0a', l1[0]='0', l1[0][0]='0' aussi
l2='0a', l2[1]='a', l2[1][0]='a' aussi
cela vient du fait que n'a plus une liste de liste de caractères l=[['0','a'],['0','a']] mais une liste de chaine l=['0a','0a'] (en quelque sorte, tu "perds" 1 niveau de liste).
Je reviens sur le if(i==5) dans la boucle qui ne permet donc de lire actuellement que les lignes 5 et 6 du fichier. c'est normal ? j'aurai fait comme dans le code de mps plus haut (faire une boucle pour lire les 4 premières lignes, puis ensuite lire et traiter les 2 suivantes (donc en dehors de la boucle et sans if)
Pareil pour la fonction "etat_entree_et_transition(ligne)", vu l'unique instruction qu'elle fait, autant la faire directement au moment de l'appel actuel (si la fonction n'a que cette instruction à faire au final)
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.