如何检测希伯来语中的回文?

时间:2014-06-20 14:06:19

标签: python unicode internationalization hebrew palindrome

我正在为回文求解器编写一系列测试。我在希伯来语中遇到了有趣的回文:

  

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

这是一个回文,但字母Mem既有常规形式(מ)又有“最终形式”(ם),它是如何显示为单词中的最后一个字母。但是在我的程序中没有硬编码“0x5de => 0x5dd”,我无法找到一种方法来以编程方式依赖Unicode,Python或将两者视为相同的库。我尝试过的事情:

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

所有人都产生了相同的字符串。其他会导致这个问题的希伯来字母(如果有人稍后搜索)将是Kaf,Nun,Peh和Tsadeh。不,我不是希伯来语的母语。

2 个答案:

答案 0 :(得分:2)

你可以做一个稍微“严格”的答案(一个不太可能给出误报和漏报的答案),还有一点点工作。请注意,Patrick Collin的答案可能因匹配大量不相关的字符而失败,因为它们共享其unicode数据名称中的最后一个字。

您可以做的一件事是在转换最终字母时采用更严格的方法:

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
#>>> 'טעמ̀ לפת תפל מ̀עט'

这只是寻找希伯来字符,其中“FINAL”可以删除,并且这样做。


然后,您还可以使用the "new" regex module on PyPI转换为字素。

import regex

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

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

这涉及重音和其他组合字符。

答案 1 :(得分:1)

这是一个适合您当前问题的丑陋解决方案:

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))

这依赖于Python查找表中希伯来字符名称的格式,因此它可能不会完美地概括。

具体来说,你有:

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

所以除了最后一句话之外的所有内容都会给你:

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']

反向相同。但是,Unicode是一个很大的世界,所以我不确定你是否能够构建一个能够击败它的例子。