2014-06-20 8 views
7

Ich schreibe eine Reihe von Tests für einen Palindromlöser. Ich kam in der interessanten Palindrom in Hebräisch:Wie kann ich ein Palindrom auf Hebräisch erkennen?

טעם לפת תפל מעט

dem ein Palindrom ist, aber der Brief Mem hat sowohl eine regelmäßige Form (מ) und eine "endgültige Form" (ם), wie es als der letzte Buchstabe in einem Wort erscheint. Aber kurz davor, "0x5de => 0x5dd" in meinem Programm zu codieren, war ich nicht in der Lage, einen Weg zu finden, programmatisch auf Unicode, Python oder eine Bibliothek zu setzen, die beide als die gleichen behandeln würde. Dinge, die ich versucht habe:

s = 'טעם לפת תפל מעט' 
s.casefold() # Python 3.4 
s.lower() 
s.upper() 
import unicodedata 
unicodedata.normalize(...) # In case this functioned like a German Eszett 

Alle ergab die gleiche Zeichenfolge. Andere hebräische Buchstaben, die dieses Problem verursachen würden (falls jemand später danach sucht), wären Kaf, Nun, Peh und Tsadeh. Nein, ich bin kein Hebräisch.

+0

Sind das die einzigen 5 Buchstaben, die dieses Problem haben? – Dannnno

+0

Warum machst du das? Ich bin nur neugierig –

+0

Ich bin ein Programmierlehrer, versuche eine Übung zu machen, die eine einfache Lösung (ist ein Wort ein Palindrom?), Eine Zwischenlösung (ist diese englische Phrase ein Palindrom?), Und eine herausfordernde Lösung (ist diese willkürliche Reihe von "Buchstaben" ein Palindrom?). – heptadecagram

Antwort

1

Hier ist eine hässliche Lösung, die für die aktuelle Ausgabe funktioniert:

import unicodedata 

def make_map(ss): 
    return [unicodedata.name(s).split(' ')[-1] for s in ss] 

def is_palindrome(ss): 
    return make_map(ss) == make_map(reversed(ss)) 

Dies stützt sich auf die Formatierung der hebräischen Zeichennamen in Python Lookup-Tabelle, obwohl, so dass es möglicherweise nicht perfekt verallgemeinern.

Insbesondere haben Sie:

In [29]: unicodedata.name(s[2]) 
Out[29]: 'HEBREW LETTER FINAL MEM' 
... 
In [31]: unicodedata.name(s[-3]) 
Out[31]: 'HEBREW LETTER MEM' 

Also alles Strippen aber das letzte Wort gibt Ihnen:

In [35]: [unicodedata.name(s_).split(" ")[-1] for s_ in s] 
Out[35]: ['TET', 'AYIN', 'MEM', 'SPACE', 'LAMED', 'PE', 'TAV', 'SPACE', 'TAV', 'PE', 'LAMED', 'SPACE', 'MEM', 'AYIN', 'TET'] 

mit derselben in umgekehrter Richtung. Unicode ist jedoch eine große Welt, daher bin ich mir nicht sicher, ob Sie ein Beispiel erstellen können, das dies schlägt.

+0

Dies ist ein interessanter Ansatz, aber wird auf Buchstaben mit Akzenten scheitern, wenn man sie alle gleich betrachtet: "LATIN CAPITAL LETTER A MIT GRAB", "LATIN CAPITAL LETTER E MIT GRAVE". – heptadecagram

+0

In diesem Fall könnten Sie "FINAL" ignorieren, was der einzige Unterschied in den Charakternamen ist ... –

+0

@heptadecagram Ich denke, es ist wahrscheinlich, dass Sie immer ein seltsames Unicode-Zeichen finden, das einen bestimmten Ansatz unterbricht. Es gibt [viele Unicode-Charaktere] (http://www.unicode.org/Public/6.3.0/ucd/NamesList.txt), und wenn Sie alles von "CEDILLA" bis "RECHTSPUNKT DOPPELWINKEL ZITATMARK "zu" VULGAR FRACTION DREI Quartale "zu" LATIN KLEINER BRIEF O mit OGONEK UND MACRON "zu" INFORMATION DESK PERSON "zu .... etc. Ich denke, du bist SOL. –

2

Sie können eine etwas "rigorosere" Antwort geben (eine, die weniger wahrscheinlich False Positives und False Negatives liefert), mit etwas mehr Arbeit. Beachten Sie, dass die Antwort von Patrick Collin fehlschlagen kann, indem viele nicht verwandte Zeichen gefunden werden, da sie das letzte Wort in ihrem Unicode-Datennamen teilen.

Eine Sache, die Sie tun können, ist ein strengeres Vorgehen bei der Umwandlung von Endbuchstaben:

import unicodedata 

# Note the added accents 
phrase = 'טעם̀ לפת תפל מ̀עט' 

def convert_final_characters(phrase): 
    for character in phrase: 
     try: 
      name = unicodedata.name(character) 
     except ValueError: 
      yield character 
      continue 

     if "HEBREW" in name and " FINAL" in name: 
      try: 
       yield unicodedata.lookup(name.replace(" FINAL", "")) 
      except KeyError: 
       # Fails for HEBREW LETTER WIDE FINAL MEM "ﬦ", 
       # which has no non-final counterpart 
       # 
       # No failure if you first normalize to 
       # HEBREW LETTER FINAL MEM "ם" 
       yield character 
     else: 
      yield character 

phrase = "".join(convert_final_characters(phrase)) 
phrase 
#>>> 'טעמ̀ לפת תפל מ̀עט' 

Das sieht nur für hebräische Zeichen, wo „FINAL“ entfernt werden kann, und das tut.


können Sie dann konvertieren auch Grapheme the "new" regex module on PyPI verwenden.

import regex 

# "\X" matches graphemes 
graphemes = regex.findall("\X", phrase) 
graphemes 
#>>> ['ט', 'ע', 'מ̀', ' ', 'ל', 'פ', 'ת', ' ', 'ת', 'פ', 'ל', ' ', 'מ̀', 'ע', 'ט'] 

graphemes == graphemes[::-1] 
#>>> True 

Dies betrifft Akzente und andere kombinierende Zeichen.