Seite 1 von 1

Denkfehler? - Anfänger braucht Hilfe

Verfasst: Freitag 8. Mai 2009, 16:51
von Cyberx ix
Ich will zu üben ein kleines Pythonprogramm schreiben, das einen text ohne umlaute durch Buchstabenvertauschen verschlüsseln kann. Bedient wird es im Moment von Python Card aus. Nur habe ich jetzt ein Probem. die Buchstaben a, b und c werden nicht verschlüsselt. Ich glaube, dass mein Problem in den Listen liegt, in denen die Buchstaben abgespeichert sind. Ich glaube auch das es irgendwie damit zusammenhängt, wie ich die Zahl angebe, um die die Buchstaben versetzt werden sollen. Ach schaut euch das einfach mal an, und habt bitte Nachsicht mit einem Anfänger. Die vielen print's sind nur wegen der Fehlersuche da. Danke schonmal für eure Hilfe!

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: cp1252 -*-

"""
__version__ = "$Revision: 1.3 $"
__date__ = "$Date: 2004/04/14 02:38:47 $"
"""

from PythonCard import model

def schluesseln(eingabe, faktor):
    x = list(eingabe)
    woerter = eingabe.split()
    y = list(u'xyzabcdefghijklmnopqrstuvwxyzabc')
    z = list(u'XYZABCDEFGHIJKLMNOPQRSTUVWXYZABC')
    k = list(u'89012345678901234567890123456789')
    print x
    print y
    wortnummer = 1
    for wort in woerter:
               
        stelle = 0
        for buchstabe in x:
            print buchstabe
            wo = 0
            #print 'for   x   gest'
            for buchstver in y:
                #print 'for y gest'
                print 'xstelle: '+str(stelle)+' '+'xst: '+x[stelle]+' '+y[wo]

                if 5 < wo < 31:
                    if x[stelle] == y[wo]:                    
                        #print 'if stelle = wo erfolgr'
                        x[stelle] = y[wo+wortnummer*faktor]
                        #print 'xstelle: '+str(stelle)+' '+'xst: '+x[stelle]+' '+'buchst: '+buchstabe+' '+y[wo]
                        print 'out: ' + x[stelle]+ ' Vers: '+str(wortnummer*faktor)
                        break
            
                if 5 < wo < 32:
                    if x[stelle] == z[wo]:                    
                        #print 'if stelle = wo erfolgr'
                        x[stelle] = z[wo+wortnummer*faktor]
                        print 'out: ' + x[stelle]+ ' Vers: '+str(wortnummer*faktor)
                        break

                if 5 < wo < 32:
                    if x[stelle] == k[wo]:                    
                        #print 'if stelle = wo erfolgr'
                        x[stelle] = k[wo+wortnummer*faktor]
                        print 'out: ' + x[stelle]+ ' Vers: '+str(wortnummer*faktor)
                        break
                if wo <= 25:
                    wo = wo+1
                else:
                    wo = 0
            stelle = stelle +1
    if wortnummer == 1:
        wortnummer = 2
    elif wortnummer == 2:
        wortnummer = 3
    elif wortnummer == 3:
        wortnummer = 1
        
            
    xb = str(''.join(x))
    return xb
    #self.components.txtdisp.text = xb
    

class MyBackground(model.Background):

    def on_initialize(self, event):
        # if you have any initialization
        # including sizer setup, do it here
        pass
    
    def on_btnverschluesseln_mouseClick(self, event):
        self.components.txtdisp.text = schluesseln(self.components.txtdisp.text, -1)    
                
            
    def on_btnentschluesseln_mouseClick(self, event):
        self.components.txtdisp.text = schluesseln(self.components.txtdisp.text, 1)
        

if __name__ == '__main__':
    app = model.Application(MyBackground)
    app.MainLoop()

Verfasst: Freitag 8. Mai 2009, 18:18
von Dill
es wäre schön wenn du auch eine ausgabe des programms zeigen und die variablen sinnvoll benennen würdest. was soll der teil mit dem "wo"? kommentar wäre hier hilfreich...

soll das programm sowas machen?

Code: Alles auswählen

>>> alphabet="abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
>>> def crypt(c, i):
...   return alphabet[alphabet.index(c)+i]
...
>>> crypt("a", 3)
'd'
>>> crypt("z", 3)
'c'
>>> [crypt(c, 3) for c in "hallo"]
['k', 'd', 'o', 'o', 'r']
>>> "".join([crypt(c) for c in "hallo"])
'kdoor'

Verfasst: Freitag 8. Mai 2009, 19:20
von EyDu
@Dill: wenn schon das Alphabet, dann aus dem "string"-Modul.
Die Verdoppelung kann man mit "string.ascii_lowercase*2" erreichen. Ist aber vollkommen überflüssig, wenn man den Modulo-Operator benutzt.
Die eckigen Klammern im "join"-Aufruf sind ebenfalls überflüssig

Und vielleicht noch der Hinweis darauf, dass Strings eine "translate"-Methode besitzen und "maketrans" im "string"-Modul.

Verfasst: Samstag 9. Mai 2009, 07:08
von Dill
und man kann es sicher auch noch komplizierter machen, dass der herr cyba-x überhauptnixmehr versteht.

>Die eckigen Klammern im "join"-Aufruf sind ebenfalls überflüssig

an die generator-ausdrücke gewöhn ich mich nicht...
seit wann ist das eigentlich möglich?

Verfasst: Samstag 9. Mai 2009, 08:37
von Cyberx ix
Erst mal danke! Und ich mach so einen Aufwand obwohl das in so wenigen Zeilen geht. Naja so ist es halt als Anfänger. Danke. Und das mit den Variablen, ich versuche mich zu bessern!

Verfasst: Samstag 9. Mai 2009, 09:26
von Dill
wenn du jetzt meine lösung abschreibst bringt das ja nix.
die ist sicher auch nicht ideal. schau doch mal was eydu dazu angemerkt hat, evtl kannst du damit ja meine lösung verbessern...?
oder wir suchen den fehler in deinem code? dazu brauchts aber kommentare sonst ist mir der zu schwer verdaulich.

Verfasst: Samstag 9. Mai 2009, 09:48
von EyDu
Dill hat geschrieben:an die generator-ausdrücke gewöhn ich mich nicht...
seit wann ist das eigentlich möglich?
Seit 2.4.

Verfasst: Samstag 9. Mai 2009, 10:03
von Cyberx ix
Also ich hab jetzt dein Verschlüsselungsverfahren in meinen Code eingebaut. Jetzt sieht er so aus:

Code: Alles auswählen

def crypt(eingabe, i)           #Eingabe ist der zu Verschüssende Text, i ist der Verschiebungsfaktor
    woerter = eingabe.split()   
    wortnummer = 1
    ausgabe = ""
    for wort in woerter:        #Wird gebraucht, da jedes Wort einen anderen Verschiebungsfaktor besiten soll
        wortverschluesselt = ""
        print wort
        for buchstabe in wort:
            try:
                alphabet="lpsbh8Okz9Nm0wPtXMYoaQi2ZG3LR1WcTfqSvDHxVK4neIE5Cgy6JF7rBUujdAlpsbh8Okz9Nm0wPtXMYoaQi2ZG3LR1WcTfqSvDHxVK4neIE5Cgy6JF7rBUujdA" 
                wortverschluesselt += alphabet[alphabet.index(buchstabe)+i*wortnummer]
                print wortverschluesselt
            except ValueError:                      #Wenn Buchstabe oder Zeichen nicht in alphabet, dann nicht ersetzen
                wortverschluesselt += buchstabe
                
        
        if wortnummer == 1:
            wortnummer = 2
        elif wortnummer == 2:
            wortnummer = 3
        elif wortnummer == 3:
            wortnummer = 1
        
        ausgabe += " "+wortverschluesselt
    return ausgabe
Hoffe der ist jetzt nen bisschen besser. Zumindest funktioniert's so. Mein Problem bei der Lösung mit den Listen war, das die irgendwie nur eine bestimmte länge haben durften. Ich habe jetzt deine Lösung so umgeschrieben, dass man ganze Texte verschlüsseln kann.

Verfasst: Samstag 9. Mai 2009, 10:21
von EyDu
Der Algorithmus funktioniert so aber nicht. Versuch mal i=2000.

Alle meine Hinweise kannst du auch auf deinen jetzigen Code anwenden.

Schau dir mal die "enumerate"-Funktion an, damit kannst du dir die "wortnummer"-Berechnung zum größten teil sparen.

"wortverschluesselt" sollte auch besser eine Liste von Buchstaben sein, welche du am Ende mit "".join zusammenfügst.

Die Kommentare sollten auch nicht in der Zeile hinter dem Code stehen, sondern in einer einzelnen Zeile davor. Dann kann man es viel besser lesen. Zur Beschreibung von Funkionen gibt es übrigens Docstrings.
Hoffe der ist jetzt nen bisschen besser. Zumindest funktioniert's so. Mein Problem bei der Lösung mit den Listen war, das die irgendwie nur eine bestimmte länge haben durften. Ich habe jetzt deine Lösung so umgeschrieben, dass man ganze Texte verschlüsseln kann.
Dann hast du irgendwo einen Fehler gemacht (wahrscheinlich Zurgriff auf enien zu großen Index), Listen können beliebig lang werden.

Verfasst: Samstag 9. Mai 2009, 10:23
von numerix
Cyberx ix hat geschrieben:Zumindest funktioniert's so.
Der Satz ist verdächtig, weil er häufig impliziert, dass derjenige, der sich in dieser Weise äußert, im Grunde nicht versteht, WARUM sein Programm das macht, was es macht, aber aufgrund einiger Durchläufe mit ausgewählten Testdaten anhand des anscheinend erwünschten Ergebnisses zu dem Schluss kommt, es mache - auch mit anderen Eingabewerten und unter anderen Bedingungen - immer das, was es soll ... :)

Verfasst: Samstag 9. Mai 2009, 10:33
von Cyberx ix
Der Satz ist verdächtig, weil er häufig impliziert, dass derjenige, der sich in dieser Weise äußert, im Grunde nicht versteht, WARUM sein Programm das macht, was es macht, aber aufgrund einiger Durchläufe mit ausgewählten Testdaten anhand des anscheinend erwünschten Ergebnisses zu dem Schluss kommt, es mache - auch mit anderen Eingabewerten und unter anderen Bedingungen - immer das, was es soll ... Smile
So war das eigentlich nicht gemeint. Es war eher darauf bezogen, dass ich weiß, dass mein Code der eines Anfängers ist und dass man das ganze auch besser schreiben könnte, wenn man das Wissen dazu hätte.
Der Algorithmus funktioniert so aber nicht. Versuch mal i=2000.

Alle meine Hinweise kannst du auch auf deinen jetzigen Code anwenden.

Schau dir mal die "enumerate"-Funktion an, damit kannst du dir die "wortnummer"-Berechnung zum größten teil sparen.

"wortverschluesselt" sollte auch besser eine Liste von Buchstaben sein, welche du am Ende mit "".join zusammenfügst.

Die Kommentare sollten auch nicht in der Zeile hinter dem Code stehen, sondern in einer einzelnen Zeile davor. Dann kann man es viel besser lesen. Zur Beschreibung von Funkionen gibt es übrigens Docstrings.
Das mit dem i = 2000 ist ja klar, das funktioniet im Moment nur bis 32, weil der string "alphabet" ja nur so lang ist. Damit werde ich mich heute Abend dann mal beschäftigen, ich muss jetzt leider noch was anderes machen.

Verfasst: Samstag 9. Mai 2009, 10:42
von Dill
du hast ja hier das problem, dass i nicht zu groß werden darf. (sonst hast du einen ungültigen listenindex)
du kannst das in deinem code ganz deutlich machen, indem du etwa schreibst:

assert(i < MAXIMALES_I), "i ist zu gross"


in diesem speziellen fall stört ein zu grosses i aber garnicht, da du einfach wieder am anfang der liste anfängst wenn i zu groß wird.
dabei hilft dir der modulo-operator (%)


genreller hinweis: einer der hauptvorteile von python ist der interpreter.
probier darin erstmal die einzelteile aus, nehme sie genau unter die lupe, dann verstehst du viel schneller was passiert.

Verfasst: Samstag 9. Mai 2009, 11:58
von snafu
Hier mal mit exzessiver Nutzung des [mod]string[/mod]-Moduls, wobei ich `translate()` der Einfachheit halber außen vor lasse:

Code: Alles auswählen

import string

def very_simple_crypt(string_to_crypt, pos_to_jump):
    alphanums = string.ascii_letters + string.digits
    crypted = ''
    for char in string_to_crypt:
        if char in string.whitespace or char in string.punctuation:
            crypted += char
        else:
            pos = (pos_to_jump + alphanums.index(char)) % (len(alphanums) - 1)
            crypted += alphanums[pos]
    return crypted

Code: Alles auswählen

In [3]: very_simple_crypt('hallo', 3)
Out[3]: 'kdoor'

In [4]: very_simple_crypt('Hallo, du Mensch!', 3)
Out[4]: 'Kdoor, gx Phqvfk!'

In [5]: very_simple_crypt('Hallo, du Mensch!', 347647)
Out[5]: 'UnyyB, qH ZrAFpu!'

In [6]: very_simple_crypt('2 girls, 1 cup', 3)
Out[6]: '5 jluov, 4 fxs'

Verfasst: Samstag 9. Mai 2009, 15:18
von EyDu
Entschlüsseln könnte ein wenig schwierig werden ;-)

Code: Alles auswählen

>>> very_simple_crypt("a", 1)
'b'
>>> very_simple_crypt("9", 1)
'b'
Es muss

Code: Alles auswählen

pos = (pos_to_jump + alphanums.index(char)) % len(alphanums)
heißen.

Man sollte auch besser fragen, ob ein Zeichen umwandelbar ist, dann deckt man auch alles ab:

Code: Alles auswählen

>>> very_simple_crypt("§", 1)
Traceback (most recent call last):
  File "<pyshell#14>", line 1, in <module>
    very_simple_crypt("§", 1)
  File "C:\Programme\Python30\test.py", line 9, in very_simple_crypt
    pos = (pos_to_jump + alphanums.index(char)) % (len(alphanums)-1)
ValueError: substring not found
Edit:

Code: Alles auswählen

import string

def very_simple_crypt(string_to_crypt, pos_to_jump):
    alphanums = string.ascii_letters + string.digits
    crypted = []
    for char in string_to_crypt:
        try:
            pos = (pos_to_jump + alphanums.index(char)) % len(alphanums)
            crypted.append(alphanums[pos])
        except ValueError:
            crypted.append(char)
    
    return "".join(crypted)

Verfasst: Samstag 9. Mai 2009, 17:23
von Cyberx ix
Ich glaube ich werde mich jetzt erstmal mit dem modulo-operator (%) und danach mit dem string-Modul beschäftigen. Also heute bringe ich das aber nicht mehr hin. Mein Gehirn fängt bald an "IndexError: Index our of range" zu senden, wenn ich nicht mehr durchblicke. :D Danke für eure Tipps und eure Hilfe! Ich werde euch demnächst wieder Belästigen. Nur als Vorwarnung.

Verfasst: Sonntag 10. Mai 2009, 12:31
von snafu
@EyDu:

Ich muss zugeben, dass ich meine Version nicht mehr so ausführlich durchgetestet habe, besonders nicht auf's Entschlüsseln.