สตริงย่อยดีเอ็นเอ palindromic reverse ที่ยาวที่สุด


11

อย่างที่คุณอาจทราบในDNAมีสี่ฐานคือ adenine ( A), cytosine ( C), guanine ( G) และ thymine ( T) โดยปกติAพันธบัตรTและCหุ้นกู้ที่มีGรูป "ขั้นบันได" ของโครงสร้างดีเอ็นเอเกลียวคู่

เรากำหนดส่วนประกอบของฐานในการเป็นฐานมันพันธบัตร - คือส่วนเติมเต็มของAเป็นTส่วนประกอบของการTเป็นAส่วนประกอบของCเป็นGและส่วนประกอบของมีG Cนอกจากนี้เรายังสามารถกำหนดส่วนประกอบของสตริงดีเอ็นเอที่จะเป็นสตริงที่มีฐานแต่ละครบครันเช่นส่วนประกอบของมีGATATCCTATAG

เนื่องจากโครงสร้างที่มีการตีเกลียวเป็นสองเท่าของดีเอ็นเอฐานในหนึ่งสาระจึงประกอบกับฐานของอีกสายหนึ่ง อย่างไรก็ตาม DNA มีทิศทางและการถอดรหัส DNA เกิดขึ้นในทิศทางตรงกันข้ามกับสองเส้น ดังนั้นนักชีววิทยาโมเลกุลมักจะสนใจในส่วนเติมกลับของสาย DNA - ค่อนข้างกลับด้านของส่วนเติมเต็มของสายอักขระ

ที่จะขยายตัวอย่างก่อนหน้านี้ของเราที่สมบูรณ์กลับGATATCเป็นไปข้างหลังเพื่อให้CTATAG GATATCดังที่คุณอาจสังเกตเห็นในตัวอย่างนี้ส่วนประกอบย้อนกลับมีค่าเท่ากับสตริงเดิม - เราเรียกสตริงดังกล่าวว่าReverse palindrome *

เมื่อได้รับสาย DNA คุณสามารถค้นหา substring ที่ยาวที่สุดซึ่งเป็น palindrome แบบย้อนกลับได้หรือไม่?

* ฉันใช้คำว่า "reverse palindrome" ซึ่งนำมาจากRosalindเพื่อแยกความแตกต่างจากความหมายปกติของ palindrome


อินพุต

ข้อมูลที่ป้อนจะเป็นสตริงเดียวที่ประกอบด้วยอักขระตัวACGTพิมพ์ใหญ่เท่านั้น คุณอาจจะเขียนฟังก์ชั่นหรือโปรแกรมเต็มรูปแบบสำหรับความท้าทายนี้

เอาท์พุต

คุณสามารถเลือกที่จะแสดงผลผ่านการพิมพ์หรือการส่งคืน (ตัวเลือกหลังจะใช้ได้เฉพาะในกรณีของฟังก์ชั่น)

โปรแกรมของคุณควรส่งสตริงย่อย palindromic reverse reverse ที่ยาวที่สุดของสายอักขระอินพุตหากมีโซลูชันเฉพาะ หากมีหลายวิธีคุณอาจส่งออกหนึ่งเดียวหรือทั้งหมด (ทางเลือกของคุณ) รายการซ้ำไม่เป็นไรหากคุณเลือกที่จะส่งออกทั้งหมด

อินพุตรับประกันว่าจะมีทางออกของความยาวอย่างน้อย 2

ทำงานตัวอย่าง

ATGGATCCG -> GGATCC

ส่วนประกอบที่ตรงกันข้ามของGGATCCมันคือ ( GGATCC --complement--> CCTAGG --reverse--> GGATCC) ดังนั้นจึงGGATCCเป็นสิ่งที่ตรงกันข้าม GATCยังเป็น palindome แบบย้อนกลับ แต่ก็ไม่ได้ยาวที่สุด

กรณีทดสอบ

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 พิมพ์ไม่ได้นานที่สุดยากกว่าการพิมพ์ทั้งหมดหรือไม่
trichoplax

หรือคุณหมายถึงการพิมพ์งานที่ยาวที่สุดทั้งหมด?
trichoplax

@githubphagocyte ใช่ความคิดเห็นที่สองของคุณ
เครื่องมือเพิ่มประสิทธิภาพ

คำตอบ:


6

Pyth, 37 36 28 24 ไบต์

ef&}TzqmaCd6T_mx4aCk6Tyz

การรวมเคล็ดลับจาก FryAmTheEggman และเคล็ดลับการตรวจสอบย้อนกลับของ Palindrome จาก Peter นี่เป็นรุ่นสั้นมาก

อย่างไรก็ตามสิ่งนี้ใช้ได้กับ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 ไบต์)

ลองออนไลน์ได้ที่นี่


UzUlzเทียบเท่ากับ
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 ความยาว
โปรแกรมเพิ่มประสิทธิภาพ

4

CJam, 39 38 ไบต์

ฉันแน่ใจว่านี้สามารถ golfed เพิ่มเติม ...

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

รับสาย DNA จาก STDIN และส่งกลับ DNA palindromic ที่ยาวที่สุดไปยัง STDOUT

ลองออนไลน์ได้ที่นี่

(คำอธิบายเร็ว ๆ นี้) (บันทึก 1 ไบต์ขอบคุณ Peter)


4

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

ดูสิไม่มีการจัดทำดัชนี! (ดียกเว้นย้อนกลับสตริงที่ไม่นับ)

iterating กว่าสตริงจะกระทำโดยการปิดตัวอักษรจากด้านหน้าและสิ้นสุดการใช้งานที่มอบหมายติดดาว ลูปด้านนอกจะลบอักขระสำหรับการเริ่มต้นSและสำหรับคำต่อท้ายแต่ละอันนั้นจะsวนซ้ำคำนำหน้าทั้งหมดของมันทดสอบทีละตัว

การทดสอบแบบย้อนกลับจะทำโดยรหัส

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

ซึ่งตรวจสอบว่าสัญลักษณ์และสตริงที่ตรงกันข้ามกันนั้นเป็นหนึ่งใน "AT", "TA", "CG" และ "GC" ฉันยังพบโซลูชัน set-based ที่จะสั้นกว่าหนึ่งตัวอักษร แต่สูญเสียสองตัวอักษรที่ต้องใช้ parens ด้านนอกเมื่อใช้

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

สิ่งนี้ยังคงรู้สึกว่าสามารถย่อให้สั้นลงได้

ในที่สุด palindrome ที่ยาวที่สุดจะถูกพิมพ์

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

ฉันหวังว่าเอาต์พุตที่คั่นด้วยช่องว่างจะโอเค หากรายชื่อดียังสามารถลบดาวออกได้ ฉันได้ลองติดตาม max วิ่งในลูปแทนรวมถึงการยัดลูปด้านในให้เป็นรายการความเข้าใจเพื่อที่ฉันจะได้รับ Max โดยตรงโดยไม่ต้องสร้าง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]

นับ shebang 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)

แรงเดรัจฉานง่าย ๆ การตรวจสอบ "reverse palindromic" ที่เกิดขึ้นจริงเป็นเพียงส่วนที่น่าสนใจเท่านั้น ที่นี่มีการเขียนอ่านง่ายขึ้น:

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.