Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Python] Inverser les caractères d'une chaine

21 février 2009 à 12:09:29

Bonjour,

J'apprend a programmer avec Python depuis peu de temps et dans le cours que je suis en train de suivre, on me propose une suite d'exercice de fin de chapitre. Cependant, le bloque sur l'un d'entre eux, voila l'énoncé :

5.9. Écrivez un script qui recopie une chaîne (dans une nouvelle variable) en l'inversant. Ainsi par exemple, « zorglub » deviendra « bulgroz ».


Après avoir posé mon algorithme (qui me semble correct), voila a quoi mon programme ressemble :

# -*- coding: utf-8 -*-
#Programme qui copie une chaine dans une autre en introduisant des '*' entre
#les caractères

ch1 = "Maison" #chaine a inversée
ch2 #chaine inversée
i, j = len(ch1) - 1, 0 #i pour valeur le nombre de caractères de ch1

#on lit ch1 a partir du dernier caractère et on les copient un par un
#dans ch2
while(i > -1):
    ch2[j] = ch1[i]

    i, j = i - 1, j + 1 

print ch2


Et voila l'erreur retournée par le compilateur :

Traceback (most recent call last):
  File "/home/nathan/Documents/informatique/programmes/scripts_python/cours/etoile_chaine.py", line 6, in <module>
    ch2 #chaine inversée
NameError: name 'ch2' is not defined


Je n'arrive pas vraiment a trouver l'origine du problème... en espérant que vous puissiez m'aider.

Merci et bonne journée.

Oze.
  • Partager sur Facebook
  • Partager sur Twitter
21 février 2009 à 12:32:02

Salut,

J'avoue ne pas avoir testé ton scipt, mais bon. Dnas ton scipt tu écris simplement "ch2", or il faudrait l'initialiser quand même. Donc j'aurias fait " ch2 = "" ". De plus il existe une méthode pour inverser une chaine de caractères facilement, du moins avec python 2.x .

chaine = "123456"
print chaine.reverse


En espérant ne pas avoir dit de bétises et de t'avoir aidé.

  • Partager sur Facebook
  • Partager sur Twitter
21 février 2009 à 14:19:59

Bonjour,
reverse ne s'applique pas sur un string.
Ta façon m'a l'air très compliqué. Tu oublies en effet de déclarer ta variable ch2 (ch2="").
Voici une façon de faire plus simple:

# -*- coding: utf-8 -*-

ch1 = "Maison" #chaine a inversée
ch2 = ""#chaine inversée

for lettre in ch1:
   ch2 = lettre + ch2 #on ajoute la lettre en premier

print ch2


Ou avec la fonction reversed() qui retourne un générateur:

# -*- coding: utf-8 -*-

ch1 = "Maison" #chaine a inversée
ch2 = ""#chaine inversée

for lettre in reversed(ch1):
    ch2 += lettre
    
print ch2
  • Partager sur Facebook
  • Partager sur Twitter
21 février 2009 à 19:35:43

Merci de votre aide mais vous utilisez des concepts que je n'ai pas encore abordé... Je doit me contenter d'une boucle de type while pour l'exercice.

EDIT : Voila se que retourne le compilateur après avoir initialisé ch2 :

Traceback (most recent call last):
  File "/home/nathan/Documents/informatique/programmes/scripts_python/cours/etoile_chaine.py", line 12, in <module>
    ch2[j] = ch1[i]
TypeError: 'str' object does not support item assignment


Oze.
  • Partager sur Facebook
  • Partager sur Twitter
21 février 2009 à 20:09:39

Une chaine est immutable en python (on ne peut pas la modifier "sur place"), c'est pour ça que l'énoncé te parle de recopie.
Tu ne peux pas modifier les caractères un par un comme ceci.
Par contre tu peux utiliser tout un tas de fonctions et d'opérateurs qui te retournent une nouvelle chaine.
Par exemple, ch3 = ch1 + ch2
  • Partager sur Facebook
  • Partager sur Twitter
22 février 2009 à 12:54:16

Bonjour

Pour reprendre le code de nyko77

tu peux faire:
ch1 = "abcde"
ch2 = "".join(reversed(ch1))


Enfin bon c'est pas ce qui t'intéresses
avec une boucle while tu peux faire comme ça:
ch1 = "abcde"
ch2 = ""
i = len(ch1) - 1 #index du dernier caractere de ch1
while i >= 0:
    ch2 += ch1[i]#on ajoute/concatène un caractere de ch1 (en partant de la fin) a ch2
    i -= 1


tu ne peux pas faire quelque chose comme:
ch2[x] = ch1[y]
avec des chaines de caractères, comme l'a dit MrGecko

Par contre si tu passes par des listes, il n'y a aucun problème !
Voici ton code utilisant les listes :
ch1 = list("Maison") #liste des caractères de la chaine a inversée
i, j = len(ch1) - 1, 0 #i pour valeur le nombre de caractères de ch1
ch2 = ["magie"]*(i+1)#liste de la chaine inversée initialisée avec n'importe quoi
#on lit ch1 a partir du dernier caractère et on les copient un par un
#dans ch2
while(i > -1):
    ch2[j] = ch1[i]
    i, j = i - 1, j + 1

print "".join(ch2)


Bon j'en p'tét un peu trop fait :-°
Mais souvient toi juste, que:
string[x] = un caractère ou autre chose
ça ne marche pas, mais :
liste[x] = quelque chose
il n'y a pas de problème ^^
  • Partager sur Facebook
  • Partager sur Twitter
22 février 2009 à 13:27:15

Ça vous vient pas à l'idée d'inverser les caractères de début et de fin du string jusqu'à arriver à la moitié ?

Tout ça sans faire une deuxième chaîne ? Faut penser à la mémoire quand même :D
  • Partager sur Facebook
  • Partager sur Twitter
22 février 2009 à 14:32:39

La mémoire ce n'est plus trop le problème des ordis de maintenant, puis dans un exo pour apprendre à programmer, on apprend pas à gérer la mémoire de façon à en consommer le moins .

On utilise au moins 2 strings + 1 int avec une boucle while, et je ne voit pas comment consommer moins que cela avec une while, et je ne suis pas sur que l'on puisse moins consommer .
  • Partager sur Facebook
  • Partager sur Twitter
22 février 2009 à 15:21:10

Citation : W3YZOH0RTH

La mémoire ce n'est plus trop le problème des ordis de maintenant


Hum, peut-être que ton PC «vista capable» à 2GB de ram, mais c'est pas le cas de tout les ordis. Puis tu te places dans le cas du desktop. Pour un serveur, va dire que ton algo consomme 4GB de ram alors que celui du concurrent en consomme 2, mais que on s'en fout, on a qu'à acheter 8GB de ram pour toute la baie.

Citation : W3YZOH0RTH

Puis dans un exo pour apprendre à programmer, on apprend pas à gérer la mémoire de façon à en consommer le moins .


Le but d'un exo pour apprendre à programmer, c'est apprendre à programmer comme il faut. Pas à faire n'importe quoi sans réfléchir.

Citation : W3YZOH0RTH

On utilise au moins 2 strings + 1 int avec une boucle while, et je ne voit pas comment consommer moins que cela avec une while, et je ne suis pas sur que l'on puisse moins consommer .


C'est très simple, un string et un unsigned. Si on néglige la taille de l'entier, ça fait pile poil deux fois moins de mémoire consommée. Et au passage, allouer et désallouer de la mémoire ça prend des cycles processeurs. Enfin, en python, on en est plus à 42 près.

Tu me diras que là on s'en fout, c'est juste mettre un string à l'envers, mais c'est à cause des gens qui pensent que la ram on s'en fout (comme toi), que l'on arrive à des horreurs comme vista…
  • Partager sur Facebook
  • Partager sur Twitter
22 février 2009 à 15:40:43

Wow wow wow !!! Calme calme !
Tout d'abord mon pc n'est pas sous vista :diable: mais ubuntu :ange: (voir windows xp de temps en temps) et n'a que 1Go de Ram .

Puis comme je vois que tu m'as l'air plutot pointilleux, je tiens à préciser que c'est dans le cadre de cet exo où la ram n'est pas importante (à moins d'etre complètement irrespectué de son ordi), Puis faire une application qui bouffe 4Go faut y aller quand meme :-° Mais t'inquiètes pas pour ma façon de programmer, j'essaye dans la mesure du possible de consommer le moins de ressources possibles proc et ram .
  • Partager sur Facebook
  • Partager sur Twitter
25 février 2009 à 11:27:16

Je crois qu'en effet, il n'en est pas au profilage de son code ;)
(Pour savoir ce qu'est le profilage, vous pouvez aller voir sur http://ftp.traduc.org/doc-vf/gazette-l [...] /lg100-L.html )

Sinon, la solution qui utilise la boucle while de W3YZOH0RTH ne parait pas mauvaise ^^
  • Partager sur Facebook
  • Partager sur Twitter
25 février 2009 à 11:49:52

Citation : SambaIsEvil

Ça vous vient pas à l'idée d'inverser les caractères de début et de fin du string jusqu'à arriver à la moitié ?

Tout ça sans faire une deuxième chaîne ? Faut penser à la mémoire quand même :D

Rappelons qu'une chaine n'est pas mutable en python.
  • Partager sur Facebook
  • Partager sur Twitter
28 février 2009 à 1:39:21

Je te donne mon code si cela peut t'aider :p ( Attention je l'ai mêler à l'exo 5.10)

ch_car = "sos" #Chaine de caractere
taille = len(ch_car) # Taille de la chaine de caractere
retire = taille - 1 #Nous retirons 1 à la variable taille car l'indice commence toujours pas 0
variable = 0 # Variable qui sert a parcourir la chaine de caractere
chaine_contraire = ch_car[retire]
chaine_retire = taille - 1
while (  chaine_retire > 0):
    chaine_retire=chaine_retire-1
    chaine_contraire= chaine_contraire + ch_car[chaine_retire]
if (ch_car == chaine_contraire):
    print "C'est un palindrome, quel que soit son sens la chaine reste la même"
else :
    print chaine_contraire
  • Partager sur Facebook
  • Partager sur Twitter
1 mars 2009 à 1:17:31

Pour Cremm:
ton code peut être grandement simplifié, et aussi plus clarifié, sans compter que certains te dirons attention à la mémoire :-° (c'est vrai que tu utilises plus de variables que nécessaires) . 'Fin bon si tu débutes ce dernier point peut être omis .

Je te conseilles notamment d'utiliser les opérateurs += et -= lors din/décrémentation de variables, de même pour la concaténation de variables .

Un truc drôle dans ton code, la variable "variable" ne sert à rien,elle est juste initialisée sans servir par la suite ^^

ton bout de code :

Citation : Cremm


taille = len(ch_car) # Taille de la chaine de caractere
retire = taille - 1 #Nous retirons 1 à la variable taille car l'indice commence toujours pas 0
variable = 0 # Variable qui sert a parcourir la chaine de caractere
chaine_contraire = ch_car[retire]
chaine_retire = taille - 1




peut être simplifié par :
chaine_retire = len(ch_car) - 1 #Nous retirons 1 à la variable taille car l'indice commence toujours pas 0
chaine_contraire = ch_car[chaine_retire]


et la boucle while:

Citation : Cremm


while (  chaine_retire > 0):
    chaine_retire=chaine_retire-1
    chaine_contraire= chaine_contraire + ch_car[chaine_retire]




par (pour la clareté):
while chaine_retire:#ici la boucle continue tant que chaine_retire n'est pas égale à 0 . étant supérieure, lorsqu'elle arrivera à 0, la boucle s'arrêtera automatiquement
    chaine_retire -= 1#on retire 1 à chaine_retire
    chaine_contraire += ch_car[chaine_retire]#on ajoute ch_car[chaine_retire] à chaine_contraire

Bon je ne sais pas si c'était volontaire de ne pas utiliser ces opérateurs mais personnellement je trouve ça plus facile à lire, après tu fais comme tu veux, c'est toi qui relis ton code après ;)

Au final ton code réadapté:
ch_car = "sos" #Chaine de caractere
chaine_retire = len(ch_car) - 1 #Nous retirons 1 à la variable taille car l'indice commence toujours pas 0
chaine_contraire = ch_car[chaine_retire]

while chaine_retire:#ici la boucle continue tant que chaine_retire n'est pas égale à 0 . étant supérieure, lorsqu'elle arrivera à 0, la boucle s'arrêtera automatiquement
    chaine_retire -= 1#on retire 1 à chaine_retire
    chaine_contraire += ch_car[chaine_retire]#on ajoute ch_car[chaine_retire] à chaine_contraire

if (ch_car == chaine_contraire):
    #plus sympa d'afficher la chaine_contraire quand même
    print "'" + chaine_contraire + "' est un palindrome, quel que soit son sens la chaine reste la même"
else :
    print chaine_contraire


Il y a d'autre moyen de formater la chaîne de caractères, mais étant donné que tu débutes c'est peut-être de ne pas t'embrouiller .
Je donne le code si ça t'intéresse quand même .
print "'%s' est un palindrome, quel que soit son sens la chaine reste la même" % (chaine_contraire)


Sinon dernier point : Pas bête de commencer par initialiser la chaîne de caractères à inverser directement par le dernier caractère de la chaîne initiale, ça fait un tour de boucle en moins, une économie de processeur ;) (de rien, mais s'en est une quand même . Ne disons pas qu'il faut la négliger, sinon on va encore me dire que c'est à cause de gens comme moi que vista existe :-° )

Désolé pour ce post relativement long, mais il me semblait que certains points devaient être soulevé .
Cordialement W3YZOH0RTH

EDIT : Un oublie que je n'aurais pas dû faire : Merci ordiclic d'avoir le même point de vue que moi sur le profilage du code,ainsi que ton lien qui ma foi était plutôt instruisant ^^
  • Partager sur Facebook
  • Partager sur Twitter
1 mars 2009 à 12:36:16

Merci pour ton aide, il est vrai que je préfère utiliser ce que le livre me dit pour le moment, mais bon je suppose que pour moi c'est beaucoup plus facile d'utiliser += etc....


Ensuite je sais que parfois avant de faire le code, je pense à d'autres solution donc forcément il y a des variable inutile qui reste. :-°
  • Partager sur Facebook
  • Partager sur Twitter
1 mars 2009 à 13:51:17

Merci de votre aide, j'ai prit l'habitude de manipuler des chaines en Python (c'est assez déroutant quand on a fait que du C jusque là).

Une autre question :

Quand j'incrémente une variable (ou que je désincrémente bien sur), mon cours m'indique d'utiliser cette synthaxe :

var = 0
var = var + 1


Peut t'on simplifier cette expression au même titre que l'on peu utiliser les opérateur "+=" ou encore "-=". J'ai essayé cette synthaxe (inspirée du C) mais elle produit une erreur à la compilation :

var++


Merci.
  • Partager sur Facebook
  • Partager sur Twitter
1 mars 2009 à 14:06:41

Pas de ++ non, mais est-ce si compliqué d'utiliser += 1 ? ;)
  • Partager sur Facebook
  • Partager sur Twitter
1 mars 2009 à 14:29:47

Non, c'était juste pour savoir si il existait la même synthaxe qu'en C pour incrémenter de 1 une variable.

Sinon, j'ai entendu dire qu'il est possible d'insérer du code C dans un script Python. J'ai chercher sur le net mais je n'ai clairement trouvé comment procéder.

  • Partager sur Facebook
  • Partager sur Twitter
1 mars 2009 à 20:34:45

Pour l'interfaçage avec le C/C++ tu as SWIG sur developpez.com
Sinon tu peux essayer le pyrex, c'est un langage fusionnant le C avec le python .
Ou tu as Cython qui est une extension pour le python afin d'intégrer du C dans le code .
Après j'ai pas cherché à essayer, même si j'y jetterais bien un oeil .

Cremm : de rien pour l'aide ^^
  • Partager sur Facebook
  • Partager sur Twitter
6 avril 2011 à 16:02:49

chaine = "test"
chaine = chaine[::-1]
print(chaine)
#affiche tset


Voila une méthode simple et efficace pour renverser une chaine de caractère. Je déterre un peu le sujet mais il me paraissait pas mal de donner une solution plus simple :D
  • Partager sur Facebook
  • Partager sur Twitter
27 juin 2020 à 16:51:42 - Message modéré pour le motif suivant : Merci d'utiliser le bouton code du forum pour insérer votre code


27 juin 2020 à 18:11:11

@ChuYounger Bonjour, merci de ne pas déterrer d'ancien sujet.

Déterrage

Citation des règles générales du forum :

Avant de poster un message, vérifiez la date du sujet dans lequel vous comptiez intervenir.

Si le dernier message sur le sujet date de plus de deux mois, mieux vaut ne pas répondre.
En effet, le déterrage d'un sujet nuit au bon fonctionnement du forum, et l'informatique pouvant grandement changer en quelques mois il n'est donc que rarement pertinent de déterrer un vieux sujet.

Au lieu de déterrer un sujet il est préférable :

  • soit de contacter directement le membre voulu par messagerie privée en cliquant sur son pseudonyme pour accéder à sa page profil, puis sur le lien "Ecrire un message"
  • soit de créer un nouveau sujet décrivant votre propre contexte
  • ne pas répondre à un déterrage et le signaler à la modération

Je ferme ce sujet. En cas de désaccord, me contacter par MP.

  • Partager sur Facebook
  • Partager sur Twitter