Найдовша зворотна паліндромна підрядок ДНК


11

Як ви знаєте, у ДНК є чотири основи - аденін ( A), цитозин ( C), гуанін ( G) та тимін ( T). Зазвичай Aзв'язки з Tі Cзв'язки з G, утворюючи "перегони" структури подвійної спіралі ДНК .

Ми визначаємо, що доповнення бази є базовим, до якого вона пов'язується - тобто доповненням Aє T, доповненням Tє A, доповненням Cє Gі доповненням Gє C. Ми також можемо визначити комплемент рядка ДНК, який буде рядком з кожною базою, доповненою, наприклад, доповненням GATATCє CTATAG.

Через дволанцюжкову структуру ДНК бази на одній ланцюгу є взаємодоповнюючими основами на іншій ланцюзі. Однак ДНК має напрямок, і транскрипція ДНК відбувається в протилежних напрямках на двох нитках. Звідси молекулярних біологів часто цікавить зворотний доповнення ланцюга ДНК - цілком буквально зворотний склад комплементу струни.

Для того, щоб розширити наш попередній приклад, зворотне доповненням GATATCє в CTATAGзворотному напрямку, так GATATC. Як ви, можливо, ви помітили, у цьому прикладі зворотний доповнення дорівнює початковому рядку - такий рядок ми називаємо зворотним паліндром . *

Враховуючи рядок ДНК, чи можете ви знайти найдовшу підрядок, який є зворотним паліндром?

* Я використовую термін "зворотний паліндром", узятий від Розалінд , для відмежування від звичайного значення паліндром.


Вхідні дані

Введенням буде одна рядок, що складається лише з символів ACGTу верхньому регістрі. Ви можете написати або функцію, або повну програму для цього завдання.

Вихідні дані

Ви можете вибрати для друку або повернення (останній вибір доступний лише у випадку функції).

Ваша програма повинна вивести найдовшу зворотну паліндромну підрядку вхідного рядка, якщо є унікальне рішення. Якщо існує кілька рішень, ви можете вивести будь-яке одне з них, або всі (на ваш вибір). Дублікати добре, якщо ви вирішите вивести їх усі.

Гарантія має рішення, що має принаймні довжину 2.

Працював приклад

ATGGATCCG -> GGATCC

Зворотний доповнення GGATCCсам по собі ( GGATCC --complement--> CCTAGG --reverse--> GGATCC), так само GGATCCє і зворотним паліндром. GATCтакож є зворотним паліндомом, але він не найдовший.

Тестові справи

AT -> AT
CGT -> CG
AGCA -> GC
GATTACA -> AT, TA
ATGGATCCG -> GGATCC
CCCCCGGGGG -> CCCCCGGGGG
ACATATATAGACT -> ATATAT, TATATA
ATTCGATCTATGTAAAGAGG -> TCGA, GATC
CGCACGTCTACGTACCTACGTAG -> CTACGTAG
TCAATGCATGCGGGTCTATATGCAT -> ATGCAT, GCATGC [, ATGCAT]
CGCTGAACTTTGCCCGTTGGTAGAACGGACTGATGTGAACGAGTGACCCG -> CG, GC, TA, AT [, GC, CG, CG, CG, CG]
CTCGCGTTTGCATAACCGTACGGGCGGAACAGTCGGCGGTGCCTCCCAGG -> CCGTACGG

Оцінка балів

Це кодовий гольф, тому рішення в найменших байтах виграє.


Було б приємніше, якби друк усіх мав якийсь бонус.
Оптимізатор

@Optimizer не друкує найдовше складніше, ніж надрукувати їх усі?
трихоплакс

Або ти маєш на увазі друк усіх найдовших?
трихоплакс

@githubphagocyte так, ваш другий коментар.
Оптимізатор

Відповіді:


6

Pyth, 37 36 28 24 байт

ef&}TzqmaCd6T_mx4aCk6Tyz

Поєднуючи поради від FryAmTheEggman і зворотний трюк перевірки паліндром від Пітера, це надзвичайно коротка версія.

Однак це працює лише з Pyth 3.0.1, який ви можете завантажити за цим посиланням і працювати так, як

python3 pyth.py -c "ef&}TzqmaCd6T_mx4aCk6Tyz" <<< "ATTCGATCTATGTAAAGAGG"

(тільки для Linux bash. У Windows натисніть Enter замість <<< та введіть введення)


Це моє попереднє подання - 28 байт

J"ACGT"ef&}TzqTjk_m@_JxJdTyz

Завдяки FryAmTheEggman за цю версію. Цей створює всі можливі підмножини вхідної рядка ДНК, фільтрує підмножини за умови, що підмножина є підрядкою введення, а зворотний перетворення дорівнює самому підмножині.

Через все можливе створення підмножини це займає навіть більше пам’яті, ніж відповідь Петра.


Це моє перше подання - 36-байтне рішення.

J"ACGT"eolNfqTjk_m@_JxJdTm:zhkek^Uz2

Це точний переклад моєї відповіді CJam . Я сподівався, що це буде набагато менше, але виявляється, що відсутність методу перекладу зробила його майже схожим розміром (все ж на 2 байти менше)

Спробуйте його онлайн тут


Uzеквівалентно Ulz.
isaacg

1
J"ACGT"eolNf&}TzqTjk_m@_JxJdTyzВикористання yдля підмножини, а потім фільтрування рядків, які не є підрядками z, коротше :)
FryAmTheEggman

1
О, і якщо ви це зробите, вам не потрібно сортувати, оскільки yце вже відсортовано за довжиною. Можна просто зробитиef...
FryAmTheEggman

5

GolfScript ( 35 34 байт)

]{{..(;\);}%)}do{{6&}%.{4^}%-1%=}?

Для цілей тестування ви можете використовувати

]{{..(;\);}%.&)}do{{6&}%.{4^}%-1%=}?

що додає a .&для зменшення дублюваних зусиль.

Розсічення

]{         # Gather string into an array and do-while...
  {        #   Map over each string in the array
    ..     #     Make a couple of copies of the string
    (;     #     Remove the first character from one of them
    \);    #     Remove the last character from the other
  }%
  )        #   Extract the last string from the array
}do        # Loop until that last string is ''
           # Because of the duplication we now have an array containing every substring
           # of the original string, and if we filter to the first occurrence of each
           # string then they're in descending order of length
{          # Find the first element in the string satisfying the condition...
  {6&}%    #   Map each character in the string to its bitwise & with 6
  .{4^}%   #   Duplicate, and map each to its bitwise ^ with 4
           #   This serves to test for A <-> T, C <-> G
  -1%=     #   Reverse and test for equality
}?

q{]{__(;\);}%~}h]{:c:i6f&_4f^W%=}=в CJam. Однаковий розмір. Не намагайтесь це зробити в онлайн-компіляторі для нічого більшого, ніж 7-дюймовий вхід
Optimizer

4

CJam, 39 38 байт

Я впевнений, що це може бути додатково гольф ...

q:Q,,_m*{~Q<>}%{,~}${_"ACGT"_W%erW%=}=

Забирає ДНК-рядок від STDIN і виводить найдовшу зворотну паліндромну ДНК в STDOUT

Спробуйте його онлайн тут

(Пояснення незабаром) (Збережено 1 байт завдяки Петру)


4

Пітон 3, 125 символів

S=input()
l=[]
while S:
 s=_,*S=S
 while s:l+=[s]*all(x+y in"ATA CGC"for x,y in zip(s,s[::-1]));*s,_=s
print(*max(l,key=len))

Дивись ма, ніякої індексації! (Ну, за винятком того, щоб повернути рядок, це не враховується.)

Ітерація над підрядками виконується за допомогою зняття знаків спереду та кінця за допомогою позначення зірочкою . Зовнішня петля видаляє символи для початку S, а для кожного такого суфіксу - sпетлі над усіма префіксами, тестуючи їх по черзі.

Тестування на зворотний паліндром проводиться за кодом

all(x+y in"ATA CGC"for x,y in zip(s,s[::-1]))

який перевіряє, що кожен символ та його аналог із зворотним рядком є ​​"AT", "TA", "CG" та "GC". Я також виявив, що рішення, засноване на наборах, на один символ коротше, але при використанні втрачає два символи, коли потрібні зовнішні паролі.

set(zip(s,s[::-1]))<=set(zip("ACTG","TGAC"))

Це все ще відчуває, що його можна скоротити.

Нарешті друкується найдовший паліндром.

print(*max(l,key=len))

Я сподіваюся, що виходи, розділені пробілом, все в порядку. Якщо список також добре, зірку можна буде видалити. Я намагався відстежувати максимум бігу в циклі, а також нав'язував внутрішні цикли в розумінні списку, щоб я міг взяти макс безпосередньо, не будуючи l, і обидва вийшли трохи довше. Але, це було досить близько, що важко сказати, який підхід насправді найкращий.


Я хотів бути більш гнучким у цьому питанні, тому я не вказав точний формат виводу для прив'язаних рішень. Якщо зрозуміло, які рішення є, то це добре, тому список добре.
Sp3000

3

J (45)

{.@(\:#&.>)@,@(('ACGT'&(|.@]-:[{~3-i.)#<)\\.)

Це функція, яка займає рядок:

   {.@(\:#&.>)@,@(('ACGT'&(|.@]-:[{~3-i.)#<)\\.) 'ATGGATCCG'
┌──────┐
│GGATCC│
└──────┘

Пояснення:

{.@(\:#&.>)@,@(('ACGT'&(|.@]-:[{~3-i.)#<)\\.) 

              (                          \\.)  for each prefix of each suffix
               (                      #<)      include the argument if,
                        |.@]                      its reverse
                            -:                    is equal to
                'ACGT'&(      [{~3-i.)            the complement
            ,@                                 ravel
   (\:#&.>)@                                   sort by length of item
{.@                                            take the first one   

3

Perl - 59 байт

#!perl -p
$_=$_[~!map$_[length]=$_,/((.)(?R)?(??{'$Q5'^$+.-$+}))/gi]

Підрахувавши шебанг як один, вхід береться STDIN.

Використання зразка:

$ echo CTCGCGTTTGCATAACCGTACGGGCGGAACAGTCGGCGGTGCCTCCCAGG | perl dna.pl
CCGTACGG

3

Python 2 - 177 байт

s=raw_input()
r,l,o=range,len(s),[]
for a in[s[i:j+1]for i in r(l)for j in r(i,l)]:q=['TC GA'.index(c)-2for c in a];o+=[a if[-n for n in q][::-1]==q else'']
print max(o,key=len)

Проста груба сила. Справжня перевірка "зворотного паліндромного" - єдина цікава частина. Ось це написано легше:

check = ['TC GA'.index(c)-2 for c in substring]
if [-n for n in check][::-1] == check:
    # substring is reverse palindromic

Я роблю це на всіх можливих підрядках і вношу їх у список, якщо це правда. Якщо це неправда, я замість цього вставляю порожню рядок. Коли всі перевірки виконані, я вивожу найдовший елемент списку. Я використав порожній рядок, тому що він економить байти, не ставлячи нічого, але це також означає, що програма не задихнеться, якщо немає рішення. Він виводить порожній рядок і виходить витончено.


1
Це здається коротшим, якщо ви згладжуєте все в єдиний список незрозуміло. Мені довелося трохи змінити логіку, але я отримав 162 с s=raw_input();r,l,g=range,len(s),'TGCA';print max([a for a in[s[i:j+1]for i in r(l)for j in r(i,l)]if[g[n]for n in[~g.find(c)for c in a]]==list(a)[::-1]],key=len). Також для рядків використовуйте findнад index:)
FryAmTheEggman
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.