palindrome

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.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

cyp++ hat geschrieben: gibts noch verbesserungsvorschläge?
Na ja, will ja nicht so direkt fragen ... aber hast Du Dir mal die anderen Posts angeschaut?

Gruß,
Christian
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

cyp++ hat geschrieben:[...]
gibts noch verbesserungsvorschläge?
Ja ^^

Code: Alles auswählen

def is_palindrom(s):
    s = [c.lower() for c in s if c.isalpha()]
    return s == s[::-1] and len(s) != 0

# Test
print is_palindrom("9%$")
print is_palindrom("otto")
Dein Code ist zu lang und zu unpythonic. Dein Code erinnert an C/C++. Du kommst nicht zufällig aus der C/C++ ecke?
BlackJack

Hm ich würde das noch ein klein wenig ändern, IMHO erfüllt eine leere Zeichenkette auch die Palindrom-Eigenschaft:

Code: Alles auswählen

def is_palindrom(s):
    if not s:
        return True
    s = [c.lower() for c in s if c.isalpha()]
    return s and s == s[::-1]
cyp++
User
Beiträge: 69
Registriert: Freitag 22. September 2006, 13:54

CM hat geschrieben:
cyp++ hat geschrieben: gibts noch verbesserungsvorschläge?
Na ja, will ja nicht so direkt fragen ... aber hast Du Dir mal die anderen Posts angeschaut?

Gruß,
Christian
vll weißt du es nicht, aber ich bin anfänger 11. klasse ausbildung zum tai. das hatten wir noch alles gar nicht!
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

BlackJack hat geschrieben:Hm ich würde das noch ein klein wenig ändern, IMHO erfüllt eine leere Zeichenkette auch die Palindrom-Eigenschaft:

Code: Alles auswählen

def is_palindrom(s):
    if not s:
        return True
    s = [c.lower() for c in s if c.isalpha()]
    return s and s == s[::-1]
OK, aber nicht im sinne von einem Wort/Begriff. Otto ist ein Palindrom aber ein Leerzeichen ist einfach nichts und mMn wäre es verkehrt dann ein True zurückzugeben. Aber in weitesten Sinne magst du wohl rech haben, wie auch CM mit seinen Code.

Code: Alles auswählen

k=k.lower()
if k == k[::-1]:
     print "Ist ein Palindrom"
else:
     print "Ist kein Palindrom"
Aber danach wurde ja nicht gefragt. Die Anforderung beschränkte sich ja nur auf Begriffe und nicht auf Leerzeichen oder (wie in CMs Beispiel) auf Alle Chars.

lg

EDIT:
@cyp++:
Dabei fällt mir die regel 1 vom Zen ein: Schön ist besser als hässlich.
und die regel 3: Einfach ist besser als komplex.

EDIT2: Im ersten Edit das @cyp++ vergessen.
Zuletzt geändert von sape am Freitag 10. November 2006, 17:23, insgesamt 1-mal geändert.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

cyp++ hat geschrieben:vll weißt du es nicht, aber ich bin anfänger 11. klasse ausbildung zum tai. das hatten wir noch alles gar nicht!
Und das heißt, dass deine Programme nur das können dürfen, was ihr im Unterricht durchgekaut habt und du dich nicht anderorts informieren kannst?

Naja, dann sehe ich ziemlich schwarz für dich (nicht böse gemeint), wenn du am Schluss auch nur das können wirst, was du vorher gelernt hast. Man wächst an seinen Problemen und wie du siehst, sind die präsentierten Lösungen wesentlich einfacher als deine, also vielleicht versuchst du mal, sie zu verstehen? Kann dir auch sonst sehr helfen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

XtraNine hat geschrieben:OK, aber nicht im sinne von einem Wort/Begriff. Otto ist ein Palindrom aber ein Leerzeichen ist einfach nichts und mMn wäre es verkehrt dann ein True zurückzugeben. Aber in weitesten Sinne magst du wohl rech haben, wie auch CM mit seinen Code.
Ich hab's im engsten Sinne als Informatiker betrachtet und da fängt die induktive Definition eines Palindroms mit dem leeren Wort (ε) an. Das ist nämlich ein beliebtes Beispiel für eine Sprache die nicht von regulären Ausdrücken und deterministischen Kellerautomaten erkannt werden kann. :-)
cyp++
User
Beiträge: 69
Registriert: Freitag 22. September 2006, 13:54

ja, hast schon recht mit. aber wie soll ich das verstehen wenn ich nicht weiß was die einzelnen sachen bedeuten?

Code: Alles auswählen

def is_palindrom(s):
    if not s:
        return True
    s = [c.lower() for c in s if c.isalpha()]
    return s and s == s[::-1]
was ist def? was is_palindrom()? was macht return ( zurückkehren? zu was? ) zeile 4 u. 5 versteh ich eig gar nicht.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

cyp++ hat geschrieben:[…]
vll weißt du es nicht, aber ich bin anfänger 11. klasse ausbildung zum tai. das hatten wir noch alles gar nicht!
Ich denke nicht das er das Böse gemeint hat. Sondern wollte nur darauf hinweisen, das einige auf dein Post eingegangen sind und du dir dann auch die mühe machen solltest, die posts wenigstens zu lesen. Du hast ja schließlich nach Hilfe gefragt und dann, nach dem alle ein par vorschlage geschrieben haben, nach Verbesserungen zu fragen, ist da schon ein wenig Strange ;) Es wurden ja viel sehr kurze und gute Sachen gepostet (ausgenommen von meiner re Variante die echt schlecht ist ^^ Aber das ist ein anderes Thema)

Falls du in den posts was nicht verstehst, kannst du ja gerne nachfragen :) Ich verstehe da einige Sachen auch noch nicht wie zum beispiel BlackJacks Funktionales Beispiel ^^ Aber da steige ich auch noch durch.

Aber nun zu deinem Code. Der erinnert sehr stark an C. Und du scheinst auch noch sehr in C/C++ zu denken (habe auch noch ein wenig das Prob bei einigen Sachen). Z.B. iterierst du über ein range() und benutzt dann den Wert als index-nummer um auf ein Array (list) zuzugreifen. Das ist sehr C Typisch un nicht pythonisch. In diesem Fall iteriert man lieber gleich über das Array und hat dann das Char, anstatt auf den index zurückzugreifen um an den Cahr zu gelangen ;)

Auch Zeile 7 mit alles upper zu machen kann man sich Sparen weil es nicht benötigt wird. Mach gleich alles lower dann kannst du dir Zeile 30 ersparen. Wie gesagt die ganzen for i in range kannst du dir sparen. Iteriere lieber gleich über den string

Code: Alles auswählen

string ="Hello World"
for i in string:
      print I,
Output

Code: Alles auswählen

Hello World
Und übrigens das…
XtraNine hat geschrieben: Dabei fällt mir die regel 1 vom Zen ein: Schön ist besser als hässlich.
und die regel 3: Einfach ist besser als komplex.
…ist nicht böse gemeint, aber dein Code ist zu lang und zu komplex und total unpythonisch.

lg
Zuletzt geändert von sape am Freitag 10. November 2006, 17:39, insgesamt 1-mal geändert.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

BlackJack hat geschrieben:
XtraNine hat geschrieben:OK, aber nicht im sinne von einem Wort/Begriff. Otto ist ein Palindrom aber ein Leerzeichen ist einfach nichts und mMn wäre es verkehrt dann ein True zurückzugeben. Aber in weitesten Sinne magst du wohl rech haben, wie auch CM mit seinen Code.
Ich hab's im engsten Sinne als Informatiker betrachtet und da fängt die induktive Definition eines Palindroms mit dem leeren Wort (ε) an. Das ist nämlich ein beliebtes Beispiel für eine Sprache die nicht von regulären Ausdrücken und deterministischen Kellerautomaten erkannt werden kann. :-)
Danke für die Information. Ich werde mich diesbezüglich mit beschäftigen. Ich komme leider nicht aus der Informatik und wusste das daher nicht.

thx & lg xtra
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

cyp++ hat geschrieben:ja, hast schon recht mit. aber wie soll ich das verstehen wenn ich nicht weiß was die einzelnen sachen bedeuten?
Dann kannst du ja Fragen. Ist ja kein Beinbruch.
cyp++ hat geschrieben:was ist def? was is_palindrom()? was macht return ( zurückkehren? zu was? ) zeile 4 u. 5 versteh ich eig gar nicht.
Def bedeutet, dass danach ein Funktionsname folgt. is_palindrom ist der Name dieser Funktion. Return gibt den dahiner stehenden Wert zurück, es gibt sie an die Stelle zurück von der sich aufgerufen wurde:

Mal ein einfaches Beispiel:

Code: Alles auswählen

ein_palindrom = is_palindrom("otto")
# wird nach dem Aufruf der Funktion zu
ein_palindrom = True
Ich denke schon, dass du weißt, was Funktionen sind? Sie verhalten sich im allgemeinen ähnlich wie Funktionen in der Mathematik.

Allerdings würde ich dir wirklich raten mit einem Tutorial wie "Wie Infomatiker denken lernen" oder der deutschen Fassung von "A Byte of Python", denn das sind wirklich die Basics.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

XtraNine hat geschrieben:Ich verstehe da einige Sachen auch noch nicht wie zum beispiel BlackJacks Funktionales Beispiel
Hm, das fällt mir teilweise gar nicht mehr auf, aber es sieht wirklich ein bisschen funktional aus. Zum Vergleich in Haskell:

Code: Alles auswählen

import Char ( isAlpha, toLower )

isPalindrome "" = True
isPalindrome xs = let xs' = [toLower x | x <- xs, isAlpha x]
                   in (length xs' > 0) && (xs' == reverse xs')

main = print (isPalindrome "Satan, oscillate my metallic sonatas!")
Nachtrag: Wo ich schon bei anderen Sprachen bin, bei C würde man natürlich versuchen zu vermeiden die Zeichenkette kopieren zu müssen:

Code: Alles auswählen

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int is_palindrome(char *str)
{
    char *start = str;
    char *end = start + strlen(str);

    if (start == end) {
        return 1;
    }
    while (1) {
        while (start < end && ! isalpha(*start)) {
            ++start;
        }
        while (start < end && ! isalpha(*end)) {
            --end;
        }
        if (tolower(*start) != tolower(*end)) {
            return 0;
        }
        if (start >= end) {
            return isalpha(*start);
        }
        ++start;
        --end;
    }
}
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

SCNR - auch die C-Version kann man noch eindampfen ...

Code: Alles auswählen

#include <ctype.h> 
 #include <stdio.h> 
 #include <stdlib.h> 
 #include <string.h> 
#include "BJ.h"

/* strrev ist semi-standard,
jedoch nicht standardmaessig bei gcc */
char *strrev(char *str)
{
      char *p1, *p2;

      if (! str || ! *str)
            return str;
      for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)
      {
            *p1 ^= *p2;
            *p2 ^= *p1;
            *p1 ^= *p2;
      }
      return str;
}

/*Black Jacks enge Definition*/
int blackjack2C(char *str){
    char *str2 = str + strlen(str) -1;
    if ( !*str ) return 1;
    while( *str++ == *str2-- && *str);
    return !*str && *(--str) == *(++str2);
}

/*meine lieblingsvariante - trotz "Kopierverbot"*/
int is_palindrome2(char *str){
    char tmp[strlen(str)];
    strcpy(tmp, str);
    strrev(tmp);
    
    if (strlen(str) <= 1) return 0;
    if (strcmp(str, tmp) == 0)
        return 1;
    else
        return 0;
}

int main(){
    char* const s = "Satan, oscillate my metallic sonatas!";
    char* const s2 = "anna";
    char* const opp = "kein palindrom";


    printf ("testing is_palindrome:\n");
    printf ("'Satan, oscillate my metallic sonatas!' is a palindrome : %s\n", is_palindrome(s) ? "yes": "no" );
    printf ("'anna' is a palindrome : %s\n", is_palindrome(s2) ? "yes": "no" );
    printf ("'kein palindorm' is a palindrome : %s\n", is_palindrome(opp) ? "yes": "no" );

    printf("\n\ntesting blackjack2C:\n");
    printf ("'Satan, oscillate my metallic sonatas!' is a palindrome : %s\n", blackjack2C(s) ? "yes": "no" );
    printf ("'anna' is a palindrome : %s\n", blackjack2C(s2) ? "yes": "no" );
    printf ("'kein palindrom' is a palindrome : %s\n", blackjack2C(opp) ? "yes": "no" );

    printf("\n\ntesting cm lieblingsversion:\n");
    printf ("'Satan, oscillate my metallic sonatas!' is a palindrome : %s\n", is_palindrome2(s) ? "yes": "no" );
    printf ("'anna' is a palindrome : %s\n", is_palindrome2(s2) ? "yes": "no" );
    printf ("'kein palindrom' is a palindrome : %s\n", is_palindrome2(opp) ? "yes": "no" );
}
Allerdings ist das bloß schnell zusammengehackt - also ohne Garantie ...

Gruß,
Christian

@cyp++: Was ich noch sagen sollte: Das war auch von mir nicht böse gemeint, aber man komms sich - das ist wohl verständlich, oder? - seltsam vor wenn jemand eine so interessante Diskussion anstösst und dann keine der vorgestellten Ideen berücksichtigt. Laß Dich auf jeden Fall nicht von diesem Einstieg hier entmutigen! Wer sagt, denn, daß andere (mich eingeschlossen) bessere Einstiege in die Programmierung hatten? :D
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Ach, ja wenn ich mir so eure C varianten ansehe, fällt mir wider ein da sich den postfix Inkrement-/Dekrement-Operator vermisse :-[ Warum gibt es den nicht in Python?

lg
BlackJack

Ist ``x += 1`` zu viel Tipparbeit? In C benutze ich den meistens für Indices oder Pointer -- beides ist in Python nicht wirklich nötig, solange man nicht "exotische" Sachen macht, also zum Beispiel versucht C in Python zu programmieren.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

BlackJack hat geschrieben:Ist ``x += 1`` zu viel Tipparbeit?
[...]
^^ Neine natürlich nicht Jack und darum geht es ja nicht ;) Es gibt ein par Situationen, da würde ich mir die pre- und postfix variante wünschen.

Mal ein Beispiel (Ich weiß das Beispiel ist schlecht und in Wirklichkeit würde ich enumerate benutzen, aber wie gesagt ist nur ein Beispiel :) )

Code: Alles auswählen

table = ["spam1", "spam2", "spam3"]
cntr = 0
ntable = []

for string in table:
    ntable.append([cntr, string])
    cntr += 1
So, mit der Postfix-Inkrement könnte man sich eine Zeile sparen, weil erstmal der aktuelle wert an die Funktion übergeben wird und danach ein Inkrement stattfindet ;)

Code: Alles auswählen

for string in table:
    ntable.append([cntr++, string])
lg
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

XtraNine hat geschrieben:(Ich weiß das Beispiel ist schlecht und in Wirklichkeit würde ich enumerate benutzen, aber wie gesagt ist nur ein Beispiel :) )
Ich glaub an dieser Stelle gibt es kaum ein Sinnvolles Beispiel denn wie du selbst feststellst - selbst für diesen Fall bietet Python mit enumerate() etwas besseres an.

Die Vorteile sind einfach zu gering um einen zusätzlichen Operator zu rechtfertigen, so war es schon ein größerer Streitpunkt mit den Dekoratoren und deren Pie-Syntax.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Readability counts.
BlackJack

Eben. Das Argument "da kann man eine Zeile sparen" zieht nur wenn es dadurch lesbarer wird.

Und wenn man wirklich Zeilen sparen will, dann bitte mit `enumerate()`.

Code: Alles auswählen

table = ['spam1', 'spam2', 'spam3']
new_table = map(list, enumerate(table))
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Jack, ich meinte ja bereits das ich das im Normalfall mit enumerate machen würde. Das war ja nur ein Beispiel, weil mir auf die schnelle kein anderes eingefallen ist. :/
Antworten