Verschlüsseln von Buchstaben aber nicht von Zeichen

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.
nightm4r3^
User
Beiträge: 83
Registriert: Montag 11. Februar 2008, 15:43
Kontaktdaten:

Hallo liebe Pythonleute,
ich habe eine Frage bzw auch eher ein Anliegen.
Ich bin gerade dabei ein Proramm zu schreiben mit dem man anhand von Cäsarverschlüsselung Texte verschlüsseln kann. Ich habe nur ein Problem. Ich würde gerne Alles verschlüsseln bis auf Satzzeichen und Leerzeichen. Mein erster Ansatz war das:

Code: Alles auswählen

# -*- coding: cp1252 -*-
def verschluesseln(text, versch): 
    """ Verschlüsselungs-Algorithmus """ 

    laenge = len(text) 
    versch = int(versch)%26
    text=text.upper()
    chiffre='' 
    for i in range(0,laenge): 
        if text[i]==' ': 
            chiffre+=' ' 
        elif 65<=ord(text[i]) + versch<=90: 
            chiffre += chr(ord(text[i])+int(versch)) 
        elif ord(text[i])+ versch >90: 
            chiffre += chr(ord(text[i])+int(versch)-26) 
        elif ord(text[i])+ versch <65:
            chiffre += chr(ord(text[i])+int(versch)+26)
       
        
     print chiffre

Das Leerzeichen ist hier schon ausgenommen. Das heißt wenn ein Leerzeichen vorhanden ist wird dieses einfach wieder mit einem Leerzeichen überschrieben. Nur wie kann ich das Nun mit Satzeichen auch noch einbauen.

PS: was ich auch noch nicht geschafft habe, ist es Groß- und Kleinschreibung zu trennen. Also wer Ideen hat, kann diese gerne Posten. Und bevor jemand fragt, JA ES IST EINE HAUSAUFGABE, ABER DIESE BESTAND NUR DARIN EIN PROGRAMM ZU SCHREIBEN DAS VERSCHLÜSSELT UND ZWAR NUR IN GRO?BUCHSTABEN UND OHNE SATZZEICHEN.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Also erstmal zu deiner Version. Da kann man ein wenig was verbessern:

Code: Alles auswählen

def verschluesseln2(text, versch):
    """ Verschlüsselungs-Algorithmus """

    laenge = len(text)
    versch = int(versch)%26
    text=text.upper()
    chiffre = ''
    for zeichen in text:
        if zeichen == ' ':
            chiffre += ' '
        elif 65 <= ord(zeichen) + versch <= 90:
            chiffre += chr(ord(zeichen)+versch)
        elif ord(zeichen)+ versch >90:
            chiffre += chr(ord(zeichen)+versch-26)
        elif ord(zeichen)+ versch <65:
            chiffre += chr(ord(zeichen)+versch+26)

    return chiffre
Mal eine andere Variante, die sollte mit Sonderzeichen + Groß-/Kleinschreibung zurecht kommen. Dabei werden alle nicht ASCII Zeichen einfach durchgereicht... Man könnte auch die Konstante ASCII mit Zeichen erweitern...

Code: Alles auswählen

import string
ASCII = string.ascii_letters

def verschluesseln3(text, versch):
    max_len = len(ASCII)
    chiffre = ""
    for zeichen in text:
        if not zeichen in ASCII:
            chiffre += zeichen
        else:
            pos = ASCII.index(zeichen)
            new_pos = pos + versch
            if new_pos > max_len:
                new_pos - max_len

            chiffre += ASCII[new_pos]

    return chiffre

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Wäre es nicht viel einfacher, wenn du einfach angibst, welche Zeichen verschlüsselt werden sollen und alle anderen werden beibehalten? Entsprechende Konstanten für Buchstaben finden sich im "string"-Modul.

Mit

Code: Alles auswählen

for c in text: ...
kannst du übrigens direkt über die Buchstaben iterieren und sparst dir die ganzen Indizes. Die "map"-Funktion ist vielleicht auch noch ganz interessant für dich, dann musst du nicht für jeden Buchstaben einzeln "ord" und "chr" aufrufen.

Und wenn du es ganz einfach haben willst, dann verwendest du aus dem Modul "string" die Funktionen "translate" und "maketrans". In Verbindung mit Slicing ist die Aufgabe in wenigen zeilen gelöst.

Und warum regst du dich eigentlich darüber auf, dass sich jemand über deine Hausaufgaben beschweren könnte, obwohl dies noch niemand getan hat. Und so weit fortgeschritten wie deine Lösung ist, sieht man immerhin, dass du wohl verstanden hast, was du da tust.
BlackJack

Noch ein Verbesserungsvorschlag: Nicht mit Zahlen bei den Bereichstests, sondern mit Zeichenketten arbeiten. Etwas wie:

Code: Alles auswählen

    if 'A' <= chr(ord(zeichen) + distanz) <= 'Z':
ist weniger kryptisch als:

Code: Alles auswählen

    if 65 <= ord(zeichen) + versch <= 90:
Nicht jeder hat die ASCII-Tabelle im Kopf, aber die meisten können Buchstaben lesen. :-)

Edit: Lösungsvorschlag

Code: Alles auswählen

def caesar_crypt(key, text):
    result = list()
    for character in text:
        for low, high in ('az', 'AZ'):
            if low <= character <= high:
                range_length = ord(high) - ord(low) + 1
                character = chr(((ord(character) - ord(low) + key)
                                 % range_length + ord(low)))
                break
        result.append(character)
    return ''.join(result)


def main():
    source = 'ABCD...WXYZ abcd...wxyz, Hallo Welt.'
    encrypted = caesar_crypt(10, source)
    print encrypted
    print caesar_crypt(-10, encrypted)
nightm4r3^
User
Beiträge: 83
Registriert: Montag 11. Februar 2008, 15:43
Kontaktdaten:

Also erst mal vielen Dank für die ganzen Verbesserungsvorschlläge und so, aber wer einem Greenie wie mir einen Gefallen tun will (müsst nicht wen ihr nicht wollt) wärs nett noch ein paar Hilfen (also was man damit bewirkt oder so) dabeizuposten.


Aber auf jeden fall vielen Dank
nightm4r3^
User
Beiträge: 83
Registriert: Montag 11. Februar 2008, 15:43
Kontaktdaten:

Okay ich stell mal eine direkte Frage:

Was bedeutet denn die Zeile:

Code: Alles auswählen

for low, high in ('az', 'AZ'): 
Also was eine For-Schleife ist ist schon klar^^ nur habe ich noch nie eine For Schleife gesehen, in der 2. Zählvariablen (low, high) drin vorkommen. Könnte mir das vllt mal jemand erklären?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Was gibt es da zu erklären, teste einfach den Code:

Code: Alles auswählen

for one, two in ((1, 2), (3, 4), (5, 6), (7, 8)):
    print one, two
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Na dann will ich doch auch mal:

Code: Alles auswählen

from string import ascii_lowercase as LOW, ascii_uppercase as UP

def caesar_crypt(key, text):
    def rotate(x):
        return x[key:]+x[:key]
    
    table = string.maketrans(LOW+UP, rotate(LOW)+rotate(UP))
    return string.translate(text, table)
lunar

Was mich jetzt interessiert: Wäre ``Hello World'.encode('rot13')`` als Lösung akzeptabel gewesen?
nightm4r3^
User
Beiträge: 83
Registriert: Montag 11. Februar 2008, 15:43
Kontaktdaten:

ja leonidas das hab ich als aller erstes gemacht. Trotzdem weiß ich immer noch nicht was es bringt, wenn das Programm

Code: Alles auswählen

'a   A'
'z   Z'
ausgibt.
BlackJack

Welches Programm macht das!? Kann es sein, dass Du das mit Namen und Objekten, manchmal auch Variablen genannt, *immer* noch nicht begriffen hast!?
nightm4r3^
User
Beiträge: 83
Registriert: Montag 11. Februar 2008, 15:43
Kontaktdaten:

Ja das kann schon sein aber wie soll ich was lernen wenn ich keine Hilfe bekomme verdammt. Von den Administratoren hier bekommt man nämlich nur Nörgeleien ab und nichts brauchbares.
BlackJack

Ich weiss nicht ob man jemandem in einem Forum denken und das zum Programmieren nötigen Abstraktionsvermögen so einfach näherbringen kann.

Das was Leonidas da gezeigt hat ist eine ziemlich einfache Schleife und wenn Du da den Zusammenhang zwischen den Tupeln, den beiden Namen, und was in der Schleife dann an die Namen gebunden ist, nicht verstehst, dann weiss ich ehrlich gesagt nicht, wie man da noch weiter helfen könnte ausser Dir eine fertige Lösung vor zu setzen. Aber warte, genau die gibt es hier ja auch schon in dem Thread.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo Forumfreunde

Erstmals ein herzliches Dankeschön an Leonidas, BlackJack
und alle Forummitglieder die uns immer grosszügig und ge-
duldig, bei unseren manchmal aufreibenden Fragen unterstützen!
In der heutigen Zeit ist dies nicht selbstverständlich.

Ich persönlich finde BlackJack's Code-Optimierung der
Ceasar-Verschlüsselung einfach genial und sehr lehrreich.

Ich beschäftige mich nun schon bald fünf Jahre mit der Python
und Tkinter Programmierung. Muss aber immer wieder feststellen,
dass ich noch lange nicht alles weiss. Das zeigen immer wieder
die interessanten Beiträge in unserem Forum. Auch beim durchlesen
der massenhaft zur Verfügung stehenden Bibliotheken zeigt sich
immer wieder, dass eigentlich vieles schon fix und fertig verfügbar
wäre. Sachen welche die man versucht mühsam selber zu program-
mieren. Es braucht aber auch viel Zeit all die Literatur zu durch-
stöbern um das gewünschte zu finden. Da wird schnell einmal das
Problem mit Learning by doing gelöst. Damit entsteht auch Code
der nicht optimal ist. Man ist zufrieden, wenn der Input den
gwünschten Output ergibt.

An nightm4r3^

Nicht aufgeben!!! Auch wir alle haben einmal angefangen, so auch
unser Forumfreunde Leonidas und BlackJack. Du kannst ja ein Filter-
programm programmieren (natürlich in Python), welches unbeliebte
Ausdrücke bzw. Textfolgen eliminiert und damit den Forumtext vor
der Interpretierung entschärfen Hi.

Ich hatte einige Minuten freie Zeit um den optimierten Code
von BlackJack mit Kommentar zu ergänzen und hoffe den Code
richtig interpretiert zu haben:

[Code ausgelagert]

Gruss wuf :wink:

Edit (Leonidas): Code ausgelagert, da der Thread schon fast blockiert hat.
Take it easy Mates!
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Im Thread Caesar-Veschlüsselung ist so etwas auch noch mal implementiert, dort gibt es auch eine Lösung mit einem Ringspeicher. Die könnte man natürlich auch so modifizieren, dass sie unbekannte Zeichen in Ruhe lässt.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

@wuf: Die Bemerkung ab Zeile 18 ist etwas ungenau. Es geht nicht um die Namen, sondern um die Objekte, die daran gebunden sind. Und da wird eigentlich auch nichts in Zahlen umgewandelt, sondern die Objekte werden verglichen, wie auch immer `str.__cmp__()` und Co das intern machen. Da es bei CPython in C implementiert ist, braucht da nichts in Zahlen umgewandelt werden, denn C kennt ja nur Zahlen. :-)
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

jens:
Wenn du schon geänderten Code einfügst, der sich auf den ersten Blick nur schwer unterscheidet, dann schreibe doch bitte dazu, was du warum geändert hast. Dabei geht es weniger um mich als um den eigentlichen Adressaten.

Dein Vorschlag enthält allerdings eine Todsünde (ich glaube in den Supybot-Codeconventions heißt es in etwa "people who do this will be swiftly kicked in the head"): Konkatenieren von Strings in einer Schleife.
Grund: Bei jedem Anhängen muss ein neues String-Objekt erzeugt werden, da es immutable ist.
Abhilfe: Eine Liste verwenden (wie es BlackJack getan hat), weil dieser Datentyp dynamisch wachsen kann. Noch besser (*behaupt*) ist die Nutzung des `yield`-Statements.

P.S.: wuf, hast du so einen merkwürdigen Browser oder brichst du absichtlich die Textzeilen manuell um? Das liest sich für mich nicht unbedingt besser.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo Y0Gi

Ja ich breche die Zeilen selber um. Der Grund liegt vielleicht
darin, dass ich in meinem früheren Leben als Editor für Todes-
anzeigen bei einem Zeitung arbeitete. Da musste nebenan noch
genug Platz frei bleiben für weitere Anzeigen.

Übrigens, wenn jemand die Richtlinien für die Python-Skript
Editierung einhält bricht er auch spätestens bei 80 Zeichen
manuell um. Ich hoffe dir macht das Format von Python-Texten
keine Probleme . Dies könnte ein weitere Grund sein, dass
ich Texte generell manuell umbreche (Ein Verhalten aus meinem
neuen Leben).

Hier auf meinem Notebook habe ich ein Bildschirmformat von
1280x800 und kleine geschriebenen Texte über die ganze
Schirmbreite zerstreut sieht *ugly* aus. Diese Texte sind
sogar noch besser lesbar, wenn eine Leerzeile eingefügt
wurde.

Nette Grüsse von wuf :wink:
Take it easy Mates!
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

wuf hat geschrieben:Hier auf meinem Notebook habe ich ein Bildschirmformat von
1280x800 und kleine geschriebenen Texte über die ganze
Schirmbreite zerstreut sieht *ugly* aus. Diese Texte sind
sogar noch besser lesbar, wenn eine Leerzeile eingefügt
wurde.
Hint: man kann die breite des Browserfensters ändern, dann bricht der Browser die Texte entsprechend um. Das ist bei deinen Texten so nicht möglich.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo Leonidas

Ich vestehe jetzt was du meinst. Bis anhin habe ich die Texte in meinem KWrite-Editor aufgesetzt und dann in das Forum-Editor-Fenster kopiert. Das kommt davon, weil ich bis vor kurzem noch mit eine pionierhaften Übertragungsrate von 56 kB mittels Modem mit dem Forum kommunizierte. Ich wollte meiner TeleCom nicht die Kasse füllen durch On-Line-Editierung. Bin jetzt auf Breitband umgestiegen. So jetzt sieht es besser aus mit der Textformatierung.

OK Leonidas danke für deinen Tipp.

Gruss wuf :wink:
Zuletzt geändert von wuf am Samstag 24. Mai 2008, 16:18, insgesamt 1-mal geändert.
Take it easy Mates!
Antworten