primitive Pythagoreische Tripel

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
BlackJack

Das man `dict.has_key()` nicht mehr verwenden sollte steht ziemlich unscheinbar in der Dokumentation: http://docs.python.org/library/stdtypes ... ct.has_key

Spätestens in Python 3 merkt man es dann, weil die Methode dort nicht mehr existiert.
Benutzeravatar
JaKlaRo
User
Beiträge: 10
Registriert: Dienstag 14. Juli 2009, 11:52
Wohnort: Bochum

Hallo,
ich habe die Anregungen von numerix und BlackJack übernommen. Die Ausgabe würde ich gerne über `curses` realisieren (`urwid` habe ich mir angeschaut, bin jedoch von der Vielzahl der Methoden etwas überfordert). Ich suche derzeit ein Beispiel für `curses`, um meine unendliche Tripelliste auszugeben, Hinweise nehme ich dankbar an.

Der aktuelle Code:

http://paste.pocoo.org/show/129744/

Gruß
JaKlaRo
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Sieht doch eigentlich ganz gut aus. Nur noch ein paar Kleinigkeiten, die mir auf den ersten Blick aufgefallen sind:

"check_3_numbers" hätte ich anders benannt, da dort auch die Werte eingelesen werden. Die eigentliche Prüfung geschieht ja auch in einer anderen Funktion. Ähnliches bei "check_number".

"first_n_triples" geht noch einfacher. Meine "a" und "b" sollte man vielleicht noch durch vernünftige Namen ersetzen :roll:

Code: Alles auswählen

def first_n_triples (n):
    for counter, i in enumerate(itertools.islice(create_primitive(), n)):
        if i[0] > i[1]:
            a, b = i[1], i[0] #oder aber in gruselig: i[:2][::-1], oder i[1::-1]
        else:
            a, b = i[:2]
        
        print "%d\t%d\t%d\t%d" % (counter+1, a, b, i[2])
Deine "quit"-Funktion ist ein wenig überflüssig. Im Dictionary von "show_menu" kannst du auch gleich "sys.exit" angeben. Ich finde den Einsatz von "sys.exit" aber eher unelegant und würde die Schleife explizit beenden.

Die wait-Funktion finde ich etwas unglücklich. Wenn du unbedingt den Bildschirm löschen möchtest, dann würde ich das vor der Fehlermeldung machen (mit etwas mehr Information über den Fehler, welche Option den ungültig war) und dann direkt die neue Eingabeaufforderung anzeigen.

Einige PEP-8-Ausrutscher sind noch drin, aber die sehen mir eher nach Versehen aus und nicht systematisch.
Das Leben ist wie ein Tennisball.
Benutzeravatar
JaKlaRo
User
Beiträge: 10
Registriert: Dienstag 14. Juli 2009, 11:52
Wohnort: Bochum

Hallo,
die erste Umsetzung mit `curses` ist fertig. In der Methode `show_triples' ist eine Zeile auskommentiert, die nicht funktioniert, wo ist der Haken? :?:
In der Methode `read_n_numbers` gibt es etwas doppelten Code, soll ich diesen in eine neue Methode auslagern?
Bei einer großen Tripelliste (10000000) funktioniert das Programm nicht. :cry:
Aber:
curses.newpad(nlines, ncols)

Creates and returns a pointer to a new pad data structure with the given number of lines and columns. A pad is returned as a window object.

A pad is like a window, except that it is not restricted by the screen size, and is not necessarily associated with a particular part of the screen. Pads can be used when a large window is needed, and only a part of the window will be on the screen at one time. Automatic refreshes of pads (such as from scrolling or echoing of input) do not occur. The refresh() and noutrefresh() methods of a pad require 6 arguments to specify the part of the pad to be displayed and the location on the screen to be used for the display. The arguments are pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol; the p arguments refer to the upper left corner of the pad region to be displayed and the s arguments define a clipping box on the screen within which the pad region is to be displayed.

Die Anregungen von EyDu sind aufgenommen worden.

Gruß
JaKlaRo

http://paste.pocoo.org/show/130017/
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Warum muss man im Menü mit Space bestätigen, statt Enter?
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Die ersten Remarks würde ich in einen Docstring des Moduls verwandeln.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo,

in Zeile 63 würde ich erwarten, dass die "is_primitive"-Funktion verwendet wird.

Die while-Schleife in Zeile 140 würde ich noch so umstellen, dass das "i += 1" im try-Block steht, die beiden "continue" können dann eingespart werden. Es ginge auch noch ohne doppelten Code, aber wirklich schöner als deine Lösung ist es auch nicht. Der Ersatz von "i" und "numbers[-1]" sind für dich vielleicht aber trotzdem interessant:

Code: Alles auswählen

while len(numbers) != n:
            try:
                self.screen.addstr(self.cursory + len(numbers) + 2, self.cursorx, "> ")
                numbers += [int(self.screen.getstr())]
                if numbers[-1] < 1:
                    raise NegativeNumber(numbers[-1])
                continue
            except ValueError:
               pass
            except NegativeNumber:
                numbers.pop()

            self.screen.move(self.cursory + len(numbers) + 2, self.cursorx +  8)
            self.screen.clrtoeol()
Wenn doppelter Code nicht in eine sinnvolle Methode gepackt werden kann, dann würde ich keine Methode daraus machen. Zumindest nicht, wenn er so lokal begrenzt ist wie in diesem Fall.

Noch etwas Geschmackssache in Zeile 201:

Code: Alles auswählen

if n < self.height:
    height, width = self.height, self.width
else:
    height, width = n + 2, self.width + n / 100
pad = curses.newpad(height, width)
Die Bedingungen aus den Zeilen 227 und 230 würde ich, wie in den Zeilen davor auch, in die Bedingung darüber ziehen.

Der "\" in den Zeile 126 ist überflüssig, bei Klammern kann man sich die Kennzeichnung sparen. Das kommt in deinem Code noch etwas öfter vor.

Für Zeile 177 empfehle ich noch einen Blick in Richtung "String Formatting". Das würde ich in einer extra Zeile erledigen und nicht direkt als Parameter.

Vielleicht solltest du noch die ein oder andere Konstante einführen.

Meine Tipps und Hinweise sind aber alles nur Kleinigkeiten, der Code sieht sonst wirklich sauber aus.
Das Leben ist wie ein Tennisball.
Benutzeravatar
JaKlaRo
User
Beiträge: 10
Registriert: Dienstag 14. Juli 2009, 11:52
Wohnort: Bochum

Hallo
birkenfeld hat geschrieben:Warum muss man im Menü mit Space bestätigen, statt Enter?
Wegen:
KEY_ENTER Enter or send (unreliable)
Nachzulesen hier: http://docs.python.org/library/curses.html
Ich habe `KEY_ENTER` ausprobiert, funktioniert bei mir jedoch nicht. :?

@birkenfeld: Was soll denn dieser Link: `http://pyside.blogspot.com`?
Eydu hat geschrieben:in Zeile 63 würde ich erwarten, dass die "is_primitive"-Funktion verwendet wird.

Code: Alles auswählen

#  Der hier verwendete Algorithmus zur Erzeugung primitiver PTs
#  benutzt die zwei Hilfsvariablen "s" und "t". Für s und t
#  gelten drei Bedingungen:
#  1. t < s
#  2. s und t sind teilerfremd.
#  3. Wenn s gerade, dann t ungerade und umgekehrt.

    while True:
        for t in range(1 + s % 2, s, 2):
            if euklid_algorithm(s, t) == 1:
                yield (2 * s * t, s**2 - t**2, s**2 + t**2)
        s += 1
Die erste und dritte Bedingung wird mit `range(1 + s % 2, s, 2)` erledigt, die zweite mit `euklid_algorithm(s, t) == 1`.
Zeilen 227 und 230 hatte ich schon abgeändert, 2o1 und 140... habe ich von Dir übernommen, 177 sieht jetzt so aus:

Code: Alles auswählen

string = "%d, %d und %d sind %s Pythagoreisches Tripel%s" % \
         (leg_a, leg_b, hypothenuse, message_var[message_key][0], message_var[message_key][1])
self.screen.addstr(self.cursory + 6, self.cursorx -10, string)
Gruß und Dank
JaKlaRo
Antworten