Sottostringa di DNA palindromica inversa più lunga


11

Come forse saprai, nel DNA ci sono quattro basi: adenina ( A), citosina ( C), guanina ( G) e timina ( T). Tipicamente si Alega Te si Clega G, formando i "pioli" della struttura a doppia elica del DNA .

Definiamo il complemento di una base come base a cui si lega - ovvero il complemento di Ais T, il complemento di Tis A, il complemento di Cis Ge il complemento di Gis C. Possiamo anche definire il complemento di una stringa di DNA come stringa con ciascuna base integrata, ad esempio il complemento di GATATCis CTATAG.

A causa della struttura a doppio filamento del DNA, le basi su un filamento sono complementari alle basi sull'altro filamento. Tuttavia il DNA ha una direzione e la trascrizione del DNA avviene in direzioni opposte sui due filamenti. Quindi i biologi molecolari sono spesso interessati al complemento inverso di una stringa di DNA - letteralmente il contrario del complemento della stringa.

Per estendere il nostro esempio precedente, il complemento inverso di GATATCè CTATAGall'indietro, quindi GATATC. Come avrai notato, in questo esempio il complemento inverso è uguale alla stringa originale - chiamiamo tale stringa un palindromo inverso . *

Data una serie di DNA, riesci a trovare la sottostringa più lunga che è un palindromo inverso?

* Uso il termine "palindromo inverso", tratto da Rosalind , per differenziarlo dal solito significato di palindromo.


Ingresso

L'input sarà una singola stringa composta solo da caratteri ACGT maiuscoli. Puoi scrivere una funzione o un programma completo per questa sfida.

Produzione

È possibile scegliere di stampare tramite stampa o ritorno (quest'ultima scelta è disponibile solo nel caso di una funzione).

Il tuo programma dovrebbe produrre la sottostringa palindromica inversa più lunga della stringa di input, se esiste una soluzione unica. Se esistono più soluzioni, è possibile produrre ciascuna di esse o tutte (a scelta). I duplicati vanno bene se si sceglie di emetterli tutti.

L'ingresso è garantito per avere una soluzione di almeno lunghezza 2.

Esempio lavorato

ATGGATCCG -> GGATCC

Il complemento inverso di GGATCCè stesso ( GGATCC --complement--> CCTAGG --reverse--> GGATCC), quindi GGATCCè un palindromo inverso.GATCè anche un palindome inverso, ma non è il più lungo.

Casi test

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

punteggio

Questo è il golf del codice, quindi vince la soluzione nel minor numero di byte.


Sarebbe stato più bello se la stampa di tutti loro avesse una sorta di bonus.
Ottimizzatore

@Optimizer non è la stampa solo il più lungo più difficile della stampa di tutti?
trichoplax,

O intendi stampare tutti i più lunghi?
trichoplax,

@githubphagocyte sì, il tuo secondo commento.
Ottimizzatore

Risposte:


6

Pyth, 37 36 28 24 byte

ef&}TzqmaCd6T_mx4aCk6Tyz

Combinando i suggerimenti di FryAmTheEggman e il trucco di controllo del palindromo inverso di Peter, questa è una versione super corta.

Tuttavia, questo funziona solo con Pyth 3.0.1 che puoi scaricare da questo link ed eseguire come

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

(solo Linux bash. Su Windows, premi Invio invece di <<< e quindi digita l'input)


Questa è la mia presentazione precedente - soluzione di 28 byte

J"ACGT"ef&}TzqTjk_m@_JxJdTyz

Grazie a FryAmTheEggman per questa versione. Questo crea tutti i possibili sottoinsiemi della stringa di DNA di input, filtra i sottoinsiemi a condizione che il sottoinsieme sia una sottostringa di input e il retro della trasformazione sia uguale al sottoinsieme stesso.

A causa di tutta la possibile creazione di un sottoinsieme, questo occupa ancora più memoria della risposta di Peter.


Questa è la mia prima presentazione - soluzione a 36 byte.

J"ACGT"eolNfqTjk_m@_JxJdTm:zhkek^Uz2

Questa è la traduzione esatta della mia risposta CJam . Speravo che questo sarebbe stato molto più piccolo, ma risulta che la mancanza di un metodo di traduzione ha reso le dimensioni quasi simili (comunque 2 byte più piccoli)

Provalo online qui


Uzè equivalente a Ulz.
isaacg,

1
J"ACGT"eolNf&}TzqTjk_m@_JxJdTyzL'uso ydi sottoinsiemi e il filtraggio delle stringhe che non sono sottostringhe zè più breve :)
FryAmTheEggman,

1
Oh, e se lo fai, non è necessario ordinare perché yè già ordinato per lunghezza. Puoi semplicemente fareef...
FryAmTheEggman il

5

GolfScript ( 35 34 byte)

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

A scopo di test potresti voler usare

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

che aggiunge a .& per ridurre lo sforzo duplicato.

Dissezione

]{         # 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%=}=in CJam. Stessa misura. Non provarlo nel compilatore online per qualcosa di più grande di 7 input di lunghezza
Optimizer

4

CJam, 39 38 byte

Sono sicuro che questo può essere ulteriormente approfondito ...

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

Prende la stringa di DNA da STDIN e trasmette il DNA palindromico inverso più lungo a STDOUT

Provalo online qui

(Spiegazione presto) (Salvato 1 byte grazie a Peter)


4

Python 3, 125 caratteri

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

Guarda mamma, nessuna indicizzazione! (Beh, tranne che per invertire la stringa, ciò non conta.)

L'iterazione sulle sottostringhe viene eseguita togliendo i caratteri dalla parte anteriore e terminando utilizzando l' assegnazione stellata . Il ciclo esterno rimuove i caratteri per l'inizio di S, e per ciascuno di questi suffissi, sscorre su tutti i prefissi, testandoli uno per uno.

Il test per il palindromo inverso viene eseguito dal codice

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

che verifica che ciascun simbolo e la sua controparte a stringa inversa siano uno di "AT", "TA", "CG" e "GC". Ho anche trovato una soluzione basata su set più corta di un personaggio, ma perde due caratteri quando richiede l'uso di parentesi esterne.

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

Sembra ancora che possa essere abbreviato.

Infine, viene stampato il palindromo più lungo.

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

Spero che le uscite separate da spazio siano OK. Se anche un elenco va bene, la stella potrebbe essere rimossa. Avevo provato invece a tracciare il max corrente nel loop, oltre a stipare i loop interni in una comprensione dell'elenco in modo da poter prendere il massimo direttamente senza costruire l, ed entrambi si sono rivelati leggermente più lunghi. Ma è stato abbastanza vicino che è difficile dire quale approccio sia effettivamente il migliore.


Volevo essere più flessibile con questa domanda, quindi non ho specificato un formato di output esatto per le soluzioni collegate. Se è chiaro quali sono le soluzioni, allora va bene, quindi un elenco va bene.
Sp3000,

3

J (45)

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

Questa è una funzione che accetta una stringa:

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

Spiegazione:

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

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

Contando lo shebang come uno, l'input viene preso da STDIN.

Esempio di utilizzo:

$ echo CTCGCGTTTGCATAACCGTACGGGCGGAACAGTCGGCGGTGCCTCCCAGG | perl dna.pl
CCGTACGG

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)

Forza bruta semplice. L'attuale controllo "reverse palindromic" è l'unica parte interessante. Qui è scritto più facilmente:

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

Lo faccio su ogni sottostringa possibile e li inserisco in un elenco se è vero. Se è falso, inserisco invece una stringa vuota. Al termine di tutti i controlli, restituisco l'elemento più lungo dell'elenco. Ho usato una stringa vuota perché salva i byte senza inserire nulla, ma significa anche che il programma non si strozzerà se non c'è soluzione. Emette una linea vuota ed esce con grazia.


1
Questo sembra essere più breve se si inserisce tutto in una incomprensione in un unico elenco. Ho dovuto cambiare un po 'la logica, ma ho ottenuto 162 con 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). Inoltre, per le stringhe, usa findoltre index:)
FryAmTheEggman il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.