Я думаю, вы смущены несколькими вещами. Несмотря на это, я не могу получить парсер, чтобы соответствовать самому длинному палиндрому, который, на мой взгляд, является вашей целью.
Во-первых, Word("A")
соответствует одному или нескольким A. Аналогично Word("T")
соответствует одному или нескольким T. Итак: AAAAT будет соответствовать палиндрому. Вместо этого давайте сделаем Literal("A") + ... + Literal("T")
Во-вторых, ZeroOrMore(stem)
означает, что у вас может быть несколько внутренних палиндромов. Это будет соответствовать: «A AT TA T», который не является палиндром. Вместо этого давайте сделаем Optional(stem)
.
В-третьих, оператор +
представляет собой конкатенацию, а не чередование. atRule + taRule + gcRule + cgRule
означает «палиндром AT, за которым следует палиндром TA, а затем палиндром GC, а затем палиндром CG». Вместо этого давайте использовать |
.
В-четвертых, вы вызываете locatedExpr
, должно быть новее, чем моя копия пирапса. Я включил его, и я немного изменил его использование.
Вот модифицированная программа:
from pyparsing import *
def locatedExpr(expr):
locator = Empty().setParseAction(lambda s,l,t: l)
return Group(locator("locn_start") + expr("value") + locator.copy().leaveWhitespace()("locn_end"))
stem = Forward()
atRule = Literal("A") + Optional(stem) + Literal("T")
taRule = Literal("T") + Optional(stem) + Literal("A")
gcRule = Literal("G") + Optional(stem) + Literal("C")
cgRule = Literal("C") + Optional(stem) + Literal("G")
stem << Combine(atRule | taRule | gcRule | cgRule)
lstem = locatedExpr(stem)
print(lstem.parseString('AT'))
print(lstem.parseString('ATAT'))
print(lstem.parseString("AAAGGGCCCTTTAAAGGGCCCTTT"))
Вот результат:
[[0, 'AT', 2]]
[[0, 'AT', 2]]
[[0, 'AAAGGGCCCTTT', 12]]
Обратите внимание, что результат является минимальной начальной палиндром, а не вся строка. Хотя я не думаю, что это ваша цель, я надеюсь, что мои изменения приблизит вас.
EDIT:
Если ваша цель состоит в том, чтобы определить, является ли строка палиндромом (контрастирует с «поиск палиндром в большей строки»), то эта программа может быть намного проще в использовании:
def DNA_complement(s):
d = {'A':'T', 'T':'A', 'C':'G', 'G':'C'}
return ''.join(d.get(ch,'') for ch in s)
def DNA_reversed_complement(s):
return DNA_complement(reversed(s))
def DNA_palindrome(s):
return s == DNA_reversed_complement(s)
print DNA_palindrome('AT')
print DNA_palindrome('ATAT')
print DNA_palindrome('AAAGGGCCCTTTAAAGGGCCCTTT')
Я не знаком с этим стилем палиндрома - разве ДНК-анализ использует другое определение? В других полях палиндром является словом или предложением, буквы которого одинаковы, если вся строка отменена. В вашем примере единственными палиндромами являются группы «AAA», «GGG», «CCC» и т. Д., Которые на самом деле довольно вырождены, поскольку палиндромы идут. (Я бы ожидал чего-то вроде «AAGAACCCCGGTTGGCCCCAAGAA», который читает то же самое вперед и назад.) Кроме того, почему вы используете 'foundExpr'? Он не меняет логику соответствия, а только аннотирует его с указанием начала/конца матча. – PaulMcG
"* Значение палиндрома в контексте генетики несколько отличается от определения, используемого для слов и предложений *" - https://en.wikipedia.org/wiki/Palindromic_sequence –
@user, ваш примерный код является неполным. Можете ли вы создать короткую, полную, автономную программу, демонстрирующую ошибку? См. [Mcve] для получения дополнительной информации. –