最长反向回文DNA子串


11

您可能知道,DNA中有四个碱基-腺嘌呤(A),胞嘧啶(C),鸟嘌呤(G)和胸腺嘧啶(T)。通常A与之结合TC结合G,形成DNA双螺旋结构的“梯级” 。

我们将基数的补语定义为它所键合的基数-即Ais T的补语,Tis A的补语,Cis G的补语和Gis 的补语C。我们还可以将DNA字符串的补码定义为每个碱基都互补的字符串,例如GATATCis 的补码CTATAG

由于DNA的双链结构,一条链上的碱基与另一条链上的碱基互补。但是,DNA具有方向,并且DNA转录在两条链上以相反的方向发生。因此,分子生物学家通常对DNA字符串的反向补体感兴趣-实际上是字符串的反向补体的反义。

为了扩展前面的示例,的反向补码GATATCCTATAG向后的,因此GATATC。您可能已经注意到,在此示例中,反向补码等于原始字符串-我们称此类字符串为反向回文。*

给定一串DNA,您能找到最长的反回文子串吗?

*我使用“反向回文”(Rosalind)一词来区别回文的通常含义。


输入值

输入将是仅包含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

@Optimizer不仅打印时间最长,也不比打印所有的时间更长?
trichoplax 2014年

还是您要打印所有最长的?
trichoplax 2014年

@githubphagocyte是的,您的第二条评论。
Optimizer

Answers:


6

Pyth,37 36 28 24字节

ef&}TzqmaCd6T_mx4aCk6Tyz

结合FryAmTheEggman的技巧和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这个版本。这将创建输入DNA字符串的所有可能子集,并在该子集是输入的子串且转换的逆向等于子集本身的条件下过滤子集。

由于所有可能的子集创建,这比Peter的答案占用了更多的内存。


这是我的第一次提交-36字节解决方案。

J"ACGT"eolNfqTjk_m@_JxJdTm:zhkek^Uz2

这是我的CJam答案的确切翻译。我曾希望这会小很多,但事实证明,缺乏翻译方法使它的大小几乎相似(尽管仍然小了2个字节)

在这里在线尝试


Uz等同于Ulz
isaacg 2014年

1
J"ACGT"eolNf&}TzqTjk_m@_JxJdTyz使用y子集,然后过滤掉不是子字符串的字符串z会更短:)
FryAmTheEggman 2014年

1
哦,如果这样做,则不需要排序,因为y已经按长度排序了。您可以做ef...
FryAmTheEggman 2014年

5

GolfScript(35 34字节)

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

出于测试目的,您可能希望使用

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

这增加了.&减少重复劳动。

解剖

]{         # 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提取DNA串,并将最长的反向回文DNA输出到STDOUT

在这里在线尝试

(即将进行解释) (感谢彼得,保存了1个字节)


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

看,没有索引!(好吧,除了反转字符串,这不算数。)

在子字符串上进行迭代是通过使用加星标的赋值从前端和后端取出char来完成的。外部循环会删除开头的字符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 2014年

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计为1,则从输入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)。另外,对于字符串,请使用findover index:)
FryAmTheEggman 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.