最長逆パリンドロームDNAサブストリング


11

ご存知かもしれませんが、DNAには4つの塩基があります—アデニン(A)、シトシン(C)、グアニン(G)およびチミン(T)。通常ATC結合しG、と結合して、DNA二重らせん構造の「ラング」を形成します。

塩基の補数を、結合する塩基と定義します。つまり、Ais Tの補数、Tis Aの補数、Cis Gの補数、Gis の補数ですC。また、DNA文字列の補数を、各塩基が補われた文字列、たとえばGATATCis の補数として定義することもできますCTATAG

DNAの二本鎖構造のため、一方の鎖の塩基はもう一方の鎖の塩基と相補的です。しかし、DNAには方向があり、DNA転写は2本の鎖で反対方向に起こります。そのため、分子生物学者はDNAストリングの逆相補性に興味を持っていることがよくあります。文字列の相補性の逆です。

前の例を拡張するために、の逆の補数GATATCCTATAG後方GATATCです。お気づきかもしれませんが、この例では、逆の補数は元の文字列と同じです。このような文字列を逆回文と呼びます。*

DNAの文字列が与えられた場合、逆パリンドロームである最も長い部分文字列を見つけることができますか?

*私は、パリンドロームの通常の意味と区別するために、ロザリンドから取られた「逆パリンドローム」という用語を使用します。


入力

入力はACGT、大文字の文字のみで構成される単一の文字列になります。このチャレンジのために、関数または完全なプログラムを作成できます。

出力

印刷または戻ることで出力することを選択できます(後者の選択は、関数の場合にのみ使用可能です)。

一意の解決策がある場合、プログラムは入力文字列の最長の逆パリンドローム部分文字列を出力する必要があります。複数のソリューションが存在する場合、それらのいずれか1つを出力することも、すべてを選択することもできます(選択)。すべてを出力することを選択した場合、複製は問題ありません。

入力には、少なくとも長さ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

得点

これはコードゴルフであるため、最小バイトのソリューションが勝ちます。


それらのすべてを印刷すると、何らかのボーナスがあればもっと良かったでしょう。
オプティマイザー14

@Optimizerは、すべてを印刷するよりも長く印刷するのが難しいだけではありませんか?
trichoplax 14

または、最も長いものすべてを印刷するということですか?
センモウヒラムシ

@githubphagocyteはい、2番目のコメント。
オプティマイザー14

回答:


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 14

1
J"ACGT"eolNf&}TzqTjk_m@_JxJdTyzyサブセットに使用し、サブストリングでzはないストリングをフィルターで除外する方が短い:)
FryAmTheEggman

1
ああ、それを行う場合、y既に長さでソートされているため、ソートする必要はありません。あなただけ行うことができますef...
FryAmTheEggman

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を超える長さの入力に対してはオンラインコンパイラで試さないでください
オプティマイザー14


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

見てください、索引付けはありません!(まあ、文字列を逆にすることを除いて、それは数えません。)

部分文字列の反復処理は、スター付きの割り当てを使用して、先頭と末尾から文字を削除することによって行われます。外側のループは、の先頭の文字を削除し、Sそのような各サフィックスについて、そのsすべてのプレフィックスをループし、それらを1つずつテストします。

逆回文のテストはコードによって行われます

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

これは、各シンボルとそれに対応する逆文字列が「AT」、「TA」、「CG」、「GC」のいずれかであることを確認します。また、セットベースのソリューションは1文字短くなりますが、使用時に外側の括弧が必要なため2文字を失います。

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

これはまだ短縮できるように感じます。

最後に、最長の回文が印刷されます。

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

スペースで区切られた出力が問題ないことを願っています。リストにも問題がなければ、星は削除できます。代わりに、ループ内で実行中の最大値を追跡し、リストを理解するために内側のループを詰め込み、を作成せずに直接最大値を取得できるようにしましたがl、両方ともわずかに長くなりました。しかし、どのアプローチが実際に最適かを判断するのは難しいほど十分に近かった。


この質問をもっと柔軟にしたかったので、タイドソリューションの正確な出力形式を指定しませんでした。解決策が明確な場合は問題ありませんので、リストに問題はありません。
Sp3000 14

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]

シバンを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

可能性のあるすべての部分文字列でこれを行い、それが真である場合はリストに入れます。falseの場合、代わりに空の文字列を入力します。すべてのチェックが完了したら、リストの最も長い要素を出力します。何も入れずにバイトを節約できるため、空の文字列を使用しましたが、解決策がない場合でもプログラムが停止しないことを意味します。空の行を出力し、正常に終了します。


1
これは、すべてを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 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.