String replace() + Liste

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
MrGreenlee
User
Beiträge: 1
Registriert: Samstag 21. November 2015, 23:02

Hi Leute,

Bin gerade dabei ein in einem String die Buchstaben im Alphabet jeweils um eins zu verändern, d.h. aus b wird a und aus z wird a usw. und anschließend den Prozess umzukehren, sodass am Ende der String rauskommen soll, welchen man auch eingegeben hat. Leider funktioniert der Umkehrprozess aus mir unbekannten Gründen noch nicht. :K

Vielleicht habt ihr eine Idee woran es liegen könnte?

Code: Alles auswählen

import string 

alphabet = string.ascii_lowercase

def krypt(x):
	for i in range(0,25):
		x = x.replace(alphabet[i],alphabet[i-1])
	return x

def de_krypt(x):
	for i in range(0,25):
		x = x.replace(alphabet[i-1],alphabet[i])
	return x

while (True):
	try:
		word = input("Word: ")
		break
	except SyntaxError:
		print("Try again!")

word = krypt(word)
print(word)
word = de_krypt(word)
print(word)
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@MrGreenlee: auch das "Verschlüsseln" funktioniert nicht. Versuch mal mit Papier und Bleistift nachzuvollziehen, was Schritt für Schritt passiert. Unter welchen Umständen glaubst Du, tritt ein SyntaxError auf?
BlackJack

@Sirius3: Wenn ich raten müsste verwendet der OP Python 2 und da ist es ziemlich einfach mit `input()` und einer Benutzereingabe Syntaxfehler auszulösen. :-)

@MrGreenlee: Solltest Du tatsächlich Python 2 verwenden dann vergiss `input()` und verwende `raw_input()` — damit gibt der Benutzer Zeichenketten ein. Und schreib dann die ``print``-Anweisung nicht so als wäre es eine Funktion oder mache es tatsächlich zu einer Funktion mit ``from __future__ import print_function``.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@MrGreenlee
Was passiert, wenn Dein zu verschlüsselndes Wort eine Länge < 25 Zeichen hat? Und was, wenn > 25? Und was ist eigentlich mit dem `z`?
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@mutetella: das zu verschlüsselnde Wort darf beliebig lang sein, da for-Schleife über das Alphabet geht.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@Sirius3
Stimmt... :oops:
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
kodela
User
Beiträge: 185
Registriert: Montag 12. Oktober 2015, 21:24
Wohnort: Landsberg am Lech
Kontaktdaten:

Hallo @MrGreenlee:

So müsste es doch funktionieren:

Code: Alles auswählen

#!/usr/bin/env python2.7
# -*- coding: iso-8859-1 -*-

from __future__ import print_function

def encode(text):
    e_text = ''
    for z in text:
        e_text += chr((ord(z)+1))
    return e_text
    
def decode(text):
    d_text = ''
    for z in text:
        d_text += chr((ord(z)-1))
    return d_text

def main():
    text = 'Äpfel'
    print(text)
    etext = encode(text)
    print(etext)
    dtext = decode(etext)
    print(dtext)
    
if __name__ == "__main__":
    main()
Bin mir allerdings sicher, dass uns BlackJack, Sirius3 oder ein anderer der Spezialisten hier noch eine bessere Lösung empfehlen können.

MfG, kodela

PS: Mit dem definierten Code für Python klappt es leider bei mir nicht.
BlackJack

@kodela: Du hast Randfälle nicht berücksichtigt und die beiden Funktionen sind strukturell fast identisch, das würde man entweder in eine gemeinsame Funktion herausziehen oder insgesamt nur eine Funktion schreiben.
kodela
User
Beiträge: 185
Registriert: Montag 12. Oktober 2015, 21:24
Wohnort: Landsberg am Lech
Kontaktdaten:

Danke @BlackJack,

Bei Verwendung einer Funktion für das en- und decoding könnte der Code dann so aussehen:

Code: Alles auswählen

def ende_code(encoding, text):
    e_text = ''
    for z in text:
        if encoding:
            e_text += chr((ord(z)+1))
        else:
            e_text += chr((ord(z)-1))
    return e_text

def main():
    text = 'Äpfel'
    print(text)
    etext = ende_code(True, text)
    print(etext)
    dtext = ende_code(False, etext)
    print(dtext)
    
if __name__ == "__main__":
    main()
Hier könnte man auch die In- bzw. Decrementierung in einer Zeile erledigen. Dann müsste aber -/+1 vorher einer Variable zugewiesen werden. Oder kann man das auch anders elegant lösen?

Was Du mit den Randfällen meinst, ist mir nicht ganz klar. Welche könnte es da noch geben, einen Zeilenvorschub oder ähnlich?

MfG, kodela
BlackJack

@kodela: Den variablen Teil, nämlich den Verschiebungswert einer Variablen zuweisen würde ich als Elegante Lösung sehen.

Mit Randfällen meine ich Werte für `z` bei denen die Funktion zu einer Ausnahme führt, nämlich dann wenn addieren oder abziehen zu einem Wert führt der ausserhalb des Wertebereichs von `chr()` führt.

Und das original macht ausserdem den Eindruck das nur ASCII-Buchstaben betroffen sein sollen und nicht einfach von *allen* Zeichen/Bytes eins abgezogen oder addiert werden soll, ausserdem vermute ich ganz stark das ein „wrap around” gewünscht ist, also das beim verschlüsseln aus einem 'z' ein 'a' wird. Also klassische ROT13-Kodierung mit 1 statt 13.
kodela
User
Beiträge: 185
Registriert: Montag 12. Oktober 2015, 21:24
Wohnort: Landsberg am Lech
Kontaktdaten:

Hallo @BlackJack,

ja, alles klar, ein solcher Randfall wäre zum Beispiel das Zeichen ' ü ' am oberen Randbereich der Zeichentabelle, wenn zum Beispiel nicht nur um eine, sondern um 5 Stellen verschoben würde.

Gibt es unter Berücksichtigung der Vorgabe von MrGreenlee dafür eine (einfache) Lösung?

MfG, kodela

PS: Jetzt haben sich unsere Beiträge überschnitten. Das mit dem „wrap around”-Verfahren muss ich mir erst zu Gemüte ziehen. Ich weiß, was damit gemeint ist, aber wie das elegant zu lösen ist, damit muss ich mich noch befassen.

Übrigens habe ich in der Zwischenzeit auch damit experimentiert, den Verschiebungswert einer Variablen zuzuweisen und zwar schon mit dem Aufruf der En-/Decodierung. Damit kann man variabler encodieren.
BlackJack

@kodela: Der übliche Weg ist verschieben des Wertebereichs nach 0 als Startwert, Verschiebung addieren, mit einer Modulo-Operation dafür sorgen dass man wieder im Wertebereich landet und zurück verschieben. Oder in Code (ungetestet):

Code: Alles auswählen

if 'a' <= z <= 'z':
    z = chr((ord(z) - ord('a') + offset) % 26 + ord('a'))
Unter der Annahme das die Zahlenwerte der Buchstaben 'a' bis 'z' lückenlos aufsteigend sind. (Das ist bei exotischeren Kodierungen nicht unbedingt der Fall, aber bei ASCII und damit allen die ASCII als Untermenge haben.)
kodela
User
Beiträge: 185
Registriert: Montag 12. Oktober 2015, 21:24
Wohnort: Landsberg am Lech
Kontaktdaten:

Hallo @BlackJack:

Ich verstehe was Du meinst und das funktioniert auch, so lange es sich bei den zu berücksichtigen Buchstaben um kleine handelt. Das wird schon etwas anders, wenn auch Großbuchstaben zu berücksichtigen sind. Wird der Wertebereich auf alle Zeichen, die in einem Text vorkommen können, erweitert, dann wird es noch etwas komplizierter.

In der Fragestellung ist von einer Verschiebung um genau eine Stelle nach links die Rede. Unter dieser Vorgabe würde kein einziges Zeichen unter den Tisch fallen beziehungsweise einer Sonderbehandlung bedürfen.

Noch etwas vereinfacht sähe der Code dann so aus:

Code: Alles auswählen

def en_de_coding(encoding, text):
    z_text = ''
    tiefe = (-1 if encoding else 1)
    for z in text:
        z_text += chr((ord(z)+tiefe))
    return z_text

def main():
    text = 'Kürbisse, Spinat,\nBlumenkohl und Rannen'
    print(text)
    etext = en_de_coding(True, text)
    print(etext)
    dtext = en_de_coding(False, etext)
    print(dtext)
    
if __name__ == "__main__":
    main()

# Ausgabe:
Kürbisse, Spinat,
Blumenkohl und Rannen
Jûqahrrd+Rohm`s	AktldmjngktmcQ`mmdm
Kürbisse, Spinat,
Blumenkohl und Rannen
MfG, kodela
Antworten