Substring DNA palindromik terbalik terpanjang

11

Seperti yang Anda ketahui, dalam DNA ada empat basa - adenin ( A), sitosin ( C), guanin ( G) dan timin ( T). Biasanya Aikatan dengan Tdan Cikatan dengan G, membentuk "anak tangga" dari struktur heliks ganda DNA .

Kami mendefinisikan komplemen dari basis sebagai basis yang terikat - yaitu komplemen Ais T, komplemen Tis A, komplemen Cis Gdan komplemen Gis C. Kita juga dapat mendefinisikan komplemen dari string DNA menjadi string dengan masing-masing basis dilengkapi, misalnya komplemen dari GATATCis CTATAG.

Karena struktur DNA beruntai ganda, basa pada satu untai saling melengkapi dengan basa pada untai lainnya. Namun DNA memiliki arah, dan transkripsi DNA terjadi dalam arah yang berlawanan pada kedua untaian. Oleh karena itu, para ahli biologi molekuler sering tertarik pada komplemen terbalik dari string DNA - secara harfiah kebalikan dari komplemen string.

Untuk memperpanjang contoh sebelumnya, komplemen kebalikan dari GATATCyang CTATAGmundur, jadi GATATC. Seperti yang mungkin telah Anda perhatikan, dalam contoh ini komplemen balik sama dengan string asli - kami menyebut string semacam itu sebagai palindrom terbalik . *

Diberikan string DNA, dapatkah Anda menemukan substring terpanjang yang merupakan palindrom terbalik?

* Saya menggunakan istilah "reverse palindrome", diambil dari Rosalind , untuk membedakan dari arti palindrome yang biasa.


Memasukkan

Input akan berupa string tunggal yang hanya terdiri dari karakter ACGTdalam huruf besar. Anda dapat menulis fungsi atau program lengkap untuk tantangan ini.

Keluaran

Anda dapat memilih untuk mencetak melalui pencetakan atau pengembalian (pilihan terakhir hanya tersedia jika fungsi).

Program Anda harus menampilkan substring palindromik mundur terpanjang dari string input, jika ada solusi yang unik. Jika ada beberapa solusi, maka Anda dapat mengeluarkan salah satu dari mereka, atau semuanya (pilihan Anda). Duplikat baik-baik saja jika Anda memilih untuk mengeluarkan semuanya.

Input dijamin memiliki solusi setidaknya panjang 2.

Contoh yang berhasil

ATGGATCCG -> GGATCC

Pelengkap terbalik dari GGATCCitu sendiri ( GGATCC --complement--> CCTAGG --reverse--> GGATCC), jadi GGATCCadalah palindrom terbalik. GATCjuga merupakan palindome terbalik, tetapi bukan yang terpanjang.

Uji kasus

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

Mencetak gol

Ini adalah kode golf, sehingga solusi dalam byte paling sedikit menang.

Sp3000
sumber
Akan lebih baik jika mencetak semuanya memiliki semacam bonus.
Pengoptimal
@ Opptizer bukankah mencetak yang paling lama lebih sulit daripada mencetak semuanya?
trichoplax
Atau maksud Anda mencetak semua yang terpanjang?
trichoplax
@githubphagocyte ya, komentar kedua Anda.
Pengoptimal

Jawaban:

6

Pyth, 37 36 28 24 byte

ef&}TzqmaCd6T_mx4aCk6Tyz

Menggabungkan tips dari FryAmTheEggman dan trik cek balik palindrome dari Peter, ini adalah versi super pendek.

Namun, ini hanya berfungsi dengan Pyth 3.0.1 yang dapat Anda unduh dari tautan ini dan jalankan seperti

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

(hanya linux bash. Di windows, tekan Enter, bukan <<< lalu ketik input)


Ini adalah pengajuan saya sebelumnya - solusi 28 byte

J"ACGT"ef&}TzqTjk_m@_JxJdTyz

Terima kasih kepada FryAmTheEggman untuk versi ini. Yang satu ini menciptakan semua himpunan bagian yang mungkin dari string DNA input, menyaring himpunan bagian pada kondisi bahwa subset adalah substring input dan kebalikan dari transformasi sama dengan subset itu sendiri.

Karena semua kemungkinan pembuatan subset, ini membutuhkan lebih banyak memori daripada jawaban Peter.


Ini adalah pengiriman pertama saya - solusi 36 byte.

J"ACGT"eolNfqTjk_m@_JxJdTm:zhkek^Uz2

Ini adalah terjemahan tepat dari jawaban CJam saya . Saya berharap ini akan menjadi jauh lebih kecil tetapi ternyata kurangnya metode penerjemahan membuat ukurannya hampir sama (masih 2 byte lebih kecil)

Cobalah online di sini

Pengoptimal
sumber
Uzsetara dengan Ulz.
isaacg
1
J"ACGT"eolNf&}TzqTjk_m@_JxJdTyzMenggunakan yuntuk subset dan kemudian menyaring string yang bukan substring zlebih pendek :)
FryAmTheEggman
1
Oh, dan jika Anda melakukannya, Anda tidak perlu menyortir karena ysudah diurutkan berdasarkan panjang. Anda bisa melakukannyaef...
FryAmTheEggman
5

GolfScript ( 35 34 bytes)

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

Untuk tujuan pengujian Anda mungkin ingin menggunakan

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

yang menambahkan .&untuk mengurangi upaya yang digandakan.

Pembedahan

]{         # 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
}?
Peter Taylor
sumber
q{]{__(;\);}%~}h]{:c:i6f&_4f^W%=}=di CJam. Ukuran sama. Jangan coba di kompiler online untuk input yang lebih besar dari 7 panjang
Pengoptimal
4

CJam, 39 38 byte

Saya yakin ini bisa bermain golf lebih lanjut ...

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

Mengambil string DNA dari STDIN dan mengeluarkan DNA palindromik terbalik terpanjang ke STDOUT

Cobalah online di sini

(Penjelasan segera) (Disimpan 1 byte berkat Peter)

Pengoptimal
sumber
4

Python 3, 125 karakter

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

Lihat bu, jangan mengindeks! (Yah, kecuali untuk membalikkan string, itu tidak masuk hitungan.)

Iterasi atas substring dilakukan dengan melepas karakter dari depan dan ujung menggunakan tugas yang berkilau bintangnya . Lingkaran luar menghapus karakter untuk awal S, dan untuk setiap akhiran tersebut, sloop atas semua awalan itu, menguji mereka satu per satu.

Pengujian untuk reverse palindrome dilakukan oleh kode

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

yang memeriksa bahwa setiap simbol dan pasangannya yang dibalik adalah salah satu dari "AT", "TA", "CG", dan "GC". Saya juga menemukan solusi berbasis set menjadi satu karakter lebih pendek, tetapi kehilangan dua karakter karena memerlukan paren luar saat digunakan.

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

Ini masih terasa seperti bisa dipersingkat.

Akhirnya, palindrom terpanjang dicetak.

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

Saya berharap keluaran yang dipisahkan ruang OK. Jika daftar juga baik-baik saja, bintang itu dapat dihapus. Saya telah mencoba melacak max berjalan di loop, serta menjejalkan loop batin ke dalam pemahaman daftar sehingga saya bisa mengambil max secara langsung tanpa membangun l, dan keduanya ternyata sedikit lebih lama. Tapi, itu cukup dekat sehingga sulit untuk mengatakan pendekatan mana yang terbaik.

Tidak
sumber
Saya ingin lebih fleksibel dengan pertanyaan ini jadi saya tidak menentukan format output yang tepat untuk solusi yang diikat. Jika jelas apa solusinya maka tidak apa-apa, jadi daftar tidak apa-apa.
Sp3000
3

J (45)

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

Ini adalah fungsi yang mengambil string:

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

Penjelasan:

{.@(\:#&.>)@,@(('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   
marinus
sumber
3

Perl - 59 byte

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

Menghitung shebang sebagai satu, input diambil dari STDIN.

Penggunaan sampel:

$ echo CTCGCGTTTGCATAACCGTACGGGCGGAACAGTCGGCGGTGCCTCCCAGG | perl dna.pl
CCGTACGG
primo
sumber
3

Python 2 - 177 byte

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)

Kekuatan kasar sederhana. Pemeriksaan "reverse palindromic" yang sebenarnya adalah satu-satunya bagian yang menarik. Di sini tertulis lebih mudah:

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

Saya melakukan itu pada setiap kemungkinan substring dan memasukkannya ke dalam daftar jika itu benar. Jika itu salah, saya memasukkan string kosong sebagai gantinya. Ketika semua pemeriksaan sudah selesai saya mengeluarkan elemen terpanjang dari daftar. Saya menggunakan string kosong karena menghemat byte daripada meletakkan apa-apa, tetapi itu juga berarti program tidak akan tersedak jika tidak ada solusi. Ini menghasilkan garis kosong dan keluar dengan anggun.

monmon bawah tanah
sumber
1
Ini tampaknya lebih pendek jika Anda smoosh semuanya menjadi satu daftar tanpa pemahaman. Saya harus sedikit mengubah logikanya, tetapi saya harus melakukannya 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). Juga, untuk string, gunakan findlebih dari index:)
FryAmTheEggman