Verschlüsselungsprogramm - Caesar

Code-Stücke können hier veröffentlicht werden.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Du hast auch nicht an die neun gedacht ;-)

Außerdem solltest du dir die folgenden Unterschiede klar machen:

Code: Alles auswählen

>>> str(range(10))
'[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]'
>>> map(str, range(10))
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
>>> string.digits
'0123456789'
Das Leben ist wie ein Tennisball.
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

EyDu hat geschrieben:Du hast auch nicht an die neun gedacht ;-)

Außerdem solltest du dir die folgenden Unterschiede klar machen:

Code: Alles auswählen

>>> str(range(10))
'[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]'
>>> map(str, range(10))
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
>>> string.digits
'0123456789'
Hm, ich hab ``str(range(9))`` einfach ausprobiert, und es hat geklappt, also hab ich mir da keine weiteren Gedanken gemacht. ;) Vielen vielen Dank :) Es ist dann wohl logischer string.digits oder die Methode mit ``map()`` zu verwenden.

EDIT #1: Doofe Formulierung entfernt
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

Da mein Caesar-Programm noch echt lückenhaft war, mal ein Update :wink:
http://paste.pocoo.org/show/288933/
Jetzt funktioniert sogar die Entschlüsselung :mrgreen: Die hat vorher nicht funktioniert, unbemerkt.

Edit: Ab jetzt muss eine Zahl eingegeben werden …
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Siehst schon deutlich besser aus, aber warum machst du eine Unterscheidung zwischen Groß- und Kleinbuchstaben. Das kann man alles in einem Rutsch erledigen, auch wenn das Ergebnis dann eventuell ein wenig anders ist. Möchtest du deine Codierung beibehalten, dann solltest du doppelten Code in Funktionen auslagen. Und die ganzen "j" wirst du durch die enumerate-Funktion los. Und natürlich möchtest du nicht 26 als magische Zahl benutzen, sonder die Länge der Strings.

Außerdem hätte ich noch etwas zum Nachdenken:

Code: Alles auswählen

>>> alpha = string.ascii_lowercase
>>> offset = 3
>>> dict(zip(alpha, alpha[offset:]+alpha[:offset]))
{'a': 'd', 'c': 'f', 'b': 'e', 'e': 'h', 'd': 'g', 'g': 'j', 'f': 'i', 'i': 'l', 'h': 'k', 'k': 'n', 'j': 'm', 'm': 'p', 'l': 'o', 'o': 'r', 'n': 'q', 'q': 't', 'p': 's', 's': 'v', 'r': 'u', 'u': 'x', 't': 'w', 'w': 'z', 'v': 'y', 'y': 'b', 'x': 'a', 'z': 'c'}
>>> 
Im string-Modul gibt es übrigens auch eine translate-Funktion.

Sebastian
Das Leben ist wie ein Tennisball.
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Am einfachsten bleibt aber immer noch str.encode :D

Code: Alles auswählen

>>> import string
>>> string.printable
'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
>>> string.printable.encode('rot13')
'0123456789nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

Hallo EyDu :-)
Ersteinmal: Vielen vielen Dank!
EyDu hat geschrieben:[…], aber warum machst du eine Unterscheidung zwischen Groß- und Kleinbuchstaben. Das kann man alles in einem Rutsch erledigen, auch wenn das Ergebnis dann eventuell ein wenig anders ist. […]
Okay, ich werde dann mal überlegen.
Möchtest du deine Codierung beibehalten, dann solltest du doppelten Code in Funktionen auslagen.
Was hat das mit Codierung zu tun?
Und die ganzen "j" wirst du durch die enumerate-Funktion los.
`enumerate` habe ich kurz nachdem ich das Programm am Anfang geschrieben habe kennengelernt, und habe danach nicht daran gedacht, da es ja so schon gut ist.
Und natürlich möchtest du nicht 26 als magische Zahl benutzen, sonder die Länge der Strings.
Wieso? Ist das etwa bei anderen möglicherweise anders? In der Doku steht:
The lowercase letters 'abcdefghijklmnopqrstuvwxyz'. This value is not locale-dependent and will not change.
Außerdem hätte ich noch etwas zum Nachdenken:

Code: Alles auswählen

>>> alpha = string.ascii_lowercase
>>> offset = 3
>>> dict(zip(alpha, alpha[offset:]+alpha[:offset]))
{'a': 'd', 'c': 'f', 'b': 'e', 'e': 'h', 'd': 'g', 'g': 'j', 'f': 'i', 'i': 'l', 'h': 'k', 'k': 'n', 'j': 'm', 'm': 'p', 'l': 'o', 'o': 'r', 'n': 'q', 'q': 't', 'p': 's', 's': 'v', 'r': 'u', 'u': 'x', 't': 'w', 'w': 'z', 'v': 'y', 'y': 'b', 'x': 'a', 'z': 'c'}
>>> 
Habe ich auch heute erst kennen gelernt, beim Lesen des Tutorials. Interessant, danke.
Im string-Modul gibt es übrigens auch eine translate-Funktion.
Danke, aber ich krieg es nicht hin, damit umzugehen :|
Sebastian
Jakob
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

derdon hat geschrieben:Am einfachsten bleibt aber immer noch str.encode :D

Code: Alles auswählen

>>> import string
>>> string.printable
'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
>>> string.printable.encode('rot13')
'0123456789nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
Super, nur irgendwie ein bisschen unnütze, wenn man nicht nur Rot13 machen will :roll:
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

So, jetzt habe ich es nach EyDus Tipps umgeschrieben:
http://paste.pocoo.org/show/289109/
Nur das mit ``zip()`` und ``string.translate()`` habe ich noch nicht gemacht.
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

nomnom: War ja auch nicht ernst gemeint ;)
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

derdon hat geschrieben:

Code: Alles auswählen

>>> import string
>>> string.printable
'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
>>> string.printable.encode('rot13')
'0123456789nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
ROT-13 ist mir eigentlich zu unsicher. Ich hatte eher an die doppelte Verschlüsselungsstärke gedacht. Hat schon mal jemand ROT-26 implementiert?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

/me hat geschrieben:Hat schon mal jemand ROT-26 implementiert?
Viel zu unsicher! Ich nehm 2 Mal ROT13.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Wenn ich deinen Code anpassen müsste, würde ich so vorgehen:

Code: Alles auswählen

def encrypt_caesar(shift, plain, alpha=string.ascii_letters):
    cipher = []

    for char in plain:
        for i, element in enumerate(alpha):
            if char == element:
                charnumber = (i + shift) % len(alpha)
                chipher.append(string.ascii_letters[charnumber]
                break
        else:
            cipher.append(char)

    return "".join(cipher)
Dabei ändert sich dann natürlich die Codierung, da, bei einer Verschiebung von 1, das "z" nicht mehr auf das "a" fällt, sondern auf das "A".

Das du "len" statt einer magischen Zahlen benutzen solltest hat ganz einfache Gründe: Die 26 sagt erstmal gar nichts aus und bei etwas komplexeren Programmen wirst du in zwei Wochen nicht mehr wissen, für was die Zahl steht. Und nun stelle dir vor, das du dein Programm erweiter möchtest: vielleicht etwas ganz abgefahrenes, wie das Hinzunehmen von Ziffern ;-) An wie vielen Stellen müsstest du dein Programm ändern, wenn du so etwas durchführen willst? Im Idealfall bei einer: du passt nur das Alphabet an, der Rest geht automatisch. Bei deiner alten Lösung müsstest du an mehreren Stellen basteln und darfst keine vergessen.

Der nächste Schritt bei dir ist, von der for-Schleife weg zu kommen und ein Dictionary einzusetzen (oder zunächst einmal die find-Methode auf Strings). Dann solltest du dir noch die get-Methode auf Dictionaries anschauen, mit etwas Überlegung kannst du dir auch den Sonderfall für nicht zu kodierende Zeichen einsparen.

Und zum translate:

Code: Alles auswählen

>>> translation = string.maketrans("abcdefghij", "0123456789")
>>> string.translate("Spam and Eggs", translation)
'Sp0m 0n3 E66s'
Das Leben ist wie ein Tennisball.
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

/me hat geschrieben:
derdon hat geschrieben:

Code: Alles auswählen

>>> import string
>>> string.printable
'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
>>> string.printable.encode('rot13')
'0123456789nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
ROT-13 ist mir eigentlich zu unsicher. Ich hatte eher an die doppelte Verschlüsselungsstärke gedacht. Hat schon mal jemand ROT-26 implementiert?
Hm, ich denke da an sowas:

Code: Alles auswählen

def encrypt(plain_text):
    cipher = plain_text
    return cipher

def decrypt(cipher):
    plain_text = cipher
    return plain_text

text = raw_input('Type in your text! ')
while text != '':
    text += raw_input('> ')
print "Encrypted:", encrypt(text)
print "Decrypted:", decrypt(text)
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

EyDu hat geschrieben: Dabei ändert sich dann natürlich die Codierung, da, bei einer Verschiebung von 1, das "z" nicht mehr auf das "a" fällt, sondern auf das "A".
Das möchte ich aber auf keinen Fall :/
Das du "len" statt einer magischen Zahlen benutzen solltest hat ganz einfache Gründe: Die 26 sagt erstmal gar nichts aus und bei etwas komplexeren Programmen wirst du in zwei Wochen nicht mehr wissen, für was die Zahl steht […]
Oh, ja, stimmt!
Der nächste Schritt bei dir ist, von der for-Schleife weg zu kommen und ein Dictionary einzusetzen (oder zunächst einmal die find-Methode auf Strings).
Ich habe mal das Programm umgeschrieben, dass es ``str.find()`` benutzt:
http://paste.pocoo.org/show/290419/
Dann solltest du dir noch die get-Methode auf Dictionaries anschauen, mit etwas Überlegung kannst du dir auch den Sonderfall für nicht zu kodierende Zeichen einsparen.

Und zum translate:

Code: Alles auswählen

>>> translation = string.maketrans("abcdefghij", "0123456789")
>>> string.translate("Spam and Eggs", translation)
'Sp0m 0n3 E66s'
Das kommt später dann, muss jetzt los ;)
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Das charnumber=0 kannst du einsparen.
Das Leben ist wie ein Tennisball.
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

So, mit Dictionary:
http://paste.pocoo.org/show/290515/
Aber ich fühle mich immer schlecht, wenn ich Code von anderen fast 1:1 übernehme (auch wenn ich es verstanden hab). :|
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hat es einen Grund, dass du zwei Dictionaries verwendest? ;-)
Das Leben ist wie ein Tennisball.
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

EyDu hat geschrieben:Hat es einen Grund, dass du zwei Dictionaries verwendest? ;-)
Ich denke ja. Ich möchte, dass Groß- und Kleinschreibung richtig bleiben!11!1!einself!1!1 ;-)
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Code: Alles auswählen

translation = dict(zip(l+u, l[shift:]+l[:shift]+u[shift:]+u[:shift]))
Das Leben ist wie ein Tennisball.
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

EyDu hat geschrieben:

Code: Alles auswählen

translation = dict(zip(l+u, l[shift:]+l[:shift]+u[shift:]+u[:shift]))
Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah! :idea:
http://paste.pocoo.org/show/290544/ <-- Neuer Code
Antworten