RNA zu Protein Translation

18

RNA ist wie DNA ein Molekül, das in Zellen gefunden wird, die genetische Informationen kodieren. Es besteht aus Nukleotiden , die durch die Basen Adenin (A), Cytosin (C), Guanin (G) und Uracil (U) dargestellt werden. * Ein Codon ist eine Sequenz von drei Nukleotiden.

Proteine sind große Moleküle, die eine Vielzahl von Funktionen erfüllen, wie Keratin, das in Haaren und Nägeln vorkommt, und Hämoglobin, das Sauerstoff in Blutzellen transportiert. Sie bestehen aus Aminosäuren , die in RNA-Molekülen als Codons kodiert sind. Manchmal können verschiedene Codons für dieselbe Aminosäure codieren. Jede Aminosäure wird üblicherweise durch einen einzelnen Buchstaben dargestellt, zum Beispiel steht H für Histidin.

Können Sie es bei einer gegebenen Sequenz von ACGUin den entsprechenden Proteinstring übersetzen?

* DNA besteht aus ACGT, wobei das T Thymin ist. Während der Transkription von DNA zu RNA wird Thymin durch Uracil ersetzt.


Eingang

Die Eingabe ist eine einzelne Zeichenfolge, die nur aus den Zeichen besteht ACGU in Großbuchstaben besteht. Sie können entweder eine Funktion oder ein vollständiges Programm für diese Herausforderung schreiben.

Ausgabe

Sie können auswählen, ob eine Zeichenfolge gedruckt oder zurückgegeben werden soll (die letztere Option ist nur im Fall einer Funktion verfügbar).

Die Übersetzung sollte bei einem Start - Codon (beginnen AUG, dargestellt als Mbei einem Stop - Codon (einer) und Ende UAA, UAGoder UGA, dargestellt als *). In vier Fällen ist die Eingabe möglicherweise ungültig:

  • Die Eingabe beginnt nicht mit einem Startcodon
  • Die Eingabe endet nicht mit einem Stoppcodon
  • Die Länge der Eingabe ist kein Vielfaches von 3
  • Die Eingabe enthält ein Stoppcodon, das nicht am Ende steht

In all diesen Fällen Errorsollte ausgegeben werden. Beachten Sie, dass im Gegensatz zu Stoppcodons Startcodons möglicherweise nach dem Anfang der Zeichenfolge angezeigt werden.

Andernfalls sollten Sie jedes Codon über die folgende RNA-Codontabelle in seine jeweilige Aminosäure umwandeln :

* UAA UAG UGA
A GCU GCC GCA GCG
C UGU UGC
D GAU GAC
E GAA GAG
F UUU UUC
G GGU GGC GGA GGG
H CAU CAC
I AUU AUC AUA
K AAA AAG
L UUA UUG CUU CUC CUA CUG
M AUG
N AAU AAC
P CCU CCC CCA CCG
Q CAA CAG
R CGU CGC CGA CGG AGA AGG
S UCU UCC UCA UCG AGU AGC
T ACU ACC ACA ACG
V GUU GUC GUA GUG
W UGG
Y UAU UAC

... und den übersetzten String ausgeben.

Beispiele

Ungültige Fälle:

<empty string> -> Error
AUG -> Error
UAA -> Error
AUGCUAG -> Error
AAAAAAA -> Error
GGGCACUAG -> Error
AUGAACGGA -> Error
AUGUAGUGA -> Error
AUGUUUGUUCCGUCGAAAUACCUAUGAACACGCUAA -> Error

Gültige Fälle:

AUGUGA -> M*
AUGAGGUGUAGCUGA -> MRCS*
AUGGGUGAGAAUGAAACGAUUUGCAGUUAA -> MGENETICS*
AUGCCAGUCGCACGAUUAGUUCACACGCUCUUGUAA -> MPVARLVHTLL*
AUGCUGCGGUCCUCGCAUCUAGCGUUGUGGUUAGGGUGUGUAACUUCGAGAACAGUGAGUCCCGUACCAGGUAGCAUAAUGCGAGCAAUGUCGUACGAUUCAUAG -> MLRSSHLALWLGCVTSRTVSPVPGSIMRAMSYDS*
AUGAAAAACAAGAAUACAACCACGACUAGAAGCAGGAGUAUAAUCAUGAUUCAACACCAGCAUCCACCCCCGCCUCGACGCCGGCGUCUACUCCUGCUUGAAGACGAGGAUGCAGCCGCGGCUGGAGGCGGGGGUGUAGUCGUGGUUUACUAUUCAUCCUCGUCUUGCUGGUGUUUAUUCUUGUUUUAA -> MKNKNTTTTRSRSIIMIQHQHPPPPRRRRLLLLEDEDAAAAGGGGVVVVYYSSSSCWCLFLF*

Bearbeiten: Weitere Testfälle hinzugefügt

Wertung

Das ist Codegolf, also gewinnt der Code mit den wenigsten Bytes.

Hinweis: Ich bin kein Experte für Molekularbiologie. Wenn ich etwas falsch angegeben habe, können Sie mich jederzeit korrigieren :)

Sp3000
quelle
1
Ein geeigneter Übersetzer sollte in der Lage sein, den offenen Leserahmen in einer beliebigen Zeichenfolge zu finden, nicht nur in den Zeichenfolgen, die mit AUG beginnen!
Kanadier
@canadianer Ahaha ja, das habe ich anfangs in Betracht gezogen, aber ich wollte die Frage nicht zu kompliziert machen, indem ich offene Leserahmen einfügte (oder sogar mehrere Proteine ​​aus einer einzelnen Zeichenfolge übersetzte) :)
Sp3000
Die leere Zeichenfolge wäre ein nützlicher Testfall, da sie einige Testansätze aufhebt, mit denen die decodierte Sequenz beginnt Mund endet *.
Peter Taylor
@ PeterTaylor Hinzugefügt, zusammen mit ein paar weiteren kurzen Testfällen :)
Sp3000
1
Wenn Sie ein echter Schmerz sein wollten, könnten Sie DNA anstelle von RNA verwenden, so dass Sie auch Leserahmen in Rückwärtsrichtung haben.
user137

Antworten:

6

CJam ( 97 93 92 91 Bytes)

q"GACU"f#3/{4b"GGEDAAVVRSKNTTMIRRQHPPLLWC*YSSLF"{_s"MW""I*"er}%=}%s_'*/(1<"M"=*Qa=\"Error"?

Dies ist ein Port meiner GolfScript-Lösung mit einer leicht optimierten Hash-Funktion, da zu meiner Überraschung eine Sache, die CJam nicht von GolfScript übernommen hat, darin besteht, Strings als Arrays von ganzen Zahlen zu behandeln.

Dank Optimierungsvorschlägen wurden 6 Bytes eingespart (einschließlich zwei Bytes von etwas, von dem ich dachte, dass ich es versucht habe und es nicht funktioniert hat - nicht wahr).

Peter Taylor
quelle
1
q"GACU"f#3/{4b"GGEDAAVVRSKNTTMIRRQHPPLLWC*YSSLF"{_s"MW""I*"er}%=}%s_'*/(1<"M"=*Q="Error"@?- 90
Optimierer
@Optimizer, einige davon scheinen eine Verbesserung zu sein. Aber es gibt einen Laufzeitfehler, und der Vergleich zu Qnicht [Q]nur falsch.
Peter Taylor
1. Sie haben den Code nicht richtig kopiert. Wenn der Code mehrere Zeilen in Kommentaren umfasst, wird beim Zeilenumbruch ein seltsames Unicode-Zeichen angezeigt. Sie müssen den Code dann manuell eingeben. 2. Sehen Sie die Logik, es wurde geändert, um richtig zu arbeiten, damit [Q]die QÄnderung korrekt ist.
Optimierer
@Optimizer, versuchen Sie TestfallAUGUAGUGA
Peter Taylor
1
Ah okay. Immer noch[Q] ->Qa
Optimierer
10

JavaScript (ES6) 167 177 Zeichen, in UTF8 als 167 177 Byte codiert

... also ich hoffe alle sind glücklich.

Edit Tatsächlich ist ein Sonderfall für den letzten Block nicht zu kurz. Wenn die letzten 2 (oder 1) Zeichen nicht zugeordnet sind, endet die Ergebniszeichenfolge nicht mit '*', und das ergibt trotzdem einen Fehler.

F=s=>/^M[^*]*\*$/.test(s=s.replace(/.../g,x=>
"KNKNTTTTRSRSIIMIQHQHPPPPRRRRLLLLEDEDAAAAGGGGVVVV*Y*YSSSS*CWCLFLF"
[[for(c of(r=0,x))r=r*4+"ACGU".search(c)]|r]))?s:'Error'

Erklärt

Jedes Zeichen in einem Triplett kann 4 Werte haben, es gibt also genau 4 ^ 3 == 64 Tripletts. Die C-Funktion ordnet jedes Triplett einer Zahl zwischen 0 und 63 zu. Es ist keine Fehlerprüfung erforderlich, da Eingabezeichen nur ACGU sind.

C=s=>[for(c of(r=0,s))r=r*4+"ACGU".search(c)]|r

Jedes Triplett ist einer Aminosäure zugeordnet, die durch einen einzelnen Buchstaben identifiziert wird. Wir können dies in einer 64-stelligen Zeichenfolge kodieren. Beginnen Sie mit der Codon Map, um die Zeichenfolge zu erhalten:

zz=["* UAA UAG UGA","A GCU GCC GCA GCG","C UGU UGC","D GAU GAC","E GAA GAG"
,"F UUU UUC","G GGU GGC GGA GGG","H CAU CAC","I AUU AUC AUA","K AAA AAG"
,"L UUA UUG CUU CUC CUA CUG","M AUG","N AAU AAC","P CCU CCC CCA CCG","Q CAA CAG"
,"R CGU CGC CGA CGG AGA AGG","S UCU UCC UCA UCG AGU AGC","T ACU ACC ACA ACG"
,"V GUU GUC GUA GUG","W UGG","Y UAU UAC"]
a=[],zz.map(v=>v.slice(2).split(' ').map(x=>a[C(x)]=v[0])),a.join('')

... erhält "KNKNTTTTRSRSIIMIQHQHPPPPRRRRLLLEDEDAAAAGGGGVVVV * Y * YSSSS * CWCLFLF"

Wir können also die Eingabezeichenfolge scannen und dieselbe Logik wie die C-Funktion verwenden, um den Code 0..63 und aus dem Code den Aminosäurecharakter zu erhalten. Die Ersetzungsfunktion teilt die Eingabezeichenfolge in 3 Zeichenblöcke auf, wobei schließlich 1 oder 2 Zeichen nicht verwaltet werden (was zu einer ungültigen Ergebniszeichenfolge führt, die nicht mit '*' endet).

Überprüfen Sie zum Schluss mit einem regulären Ausdruck, ob die codierte Zeichenfolge gültig ist: Sie muss mit 'M' beginnen, darf kein '*' enthalten und muss mit '*' enden.

Prüfung in der FireBug / FireFox-Konsole

;['AUGCUAG','GGGCACUAG','AUGAACGGA','AUGUAGUGA','AAAAAAA',
'AUGUUUGUUCCGUCGAAAUACCUAUGAACACGCUAA',
'AUGAGGUGUAGCUGA','AUGCCAGUCGCACGAUUAGUUCACACGCUCUUGUAA',
'AUGCUGCGGUCCUCGCAUCUAGCGUUGUGGUUAGGGUGUGUAACUUCGAGAACAGUGAGUCCCGUACCAGGUAGCAUAAUGCGAGCAAUGUCGUACGAUUCAUAG']
.forEach(c=>console.log(c,'->',F(c)))

Ausgabe

AUGCUAG -> Error
GGGCACUAG -> Error
AUGAACGGA -> Error
AUGUAGUGA -> Error
AAAAAAA -> Error
AUGUUUGUUCCGUCGAAAUACCUAUGAACACGCUAA -> Error
AUGAGGUGUAGCUGA -> MRCS*
AUGCCAGUCGCACGAUUAGUUCACACGCUCUUGUAA -> MPVARLVHTLL*
AUGCUGCGGUCCUCGCAUCUAGCGUUGUGGUUAGGGUGUGUAACUUCGAGAACAGUGAGUCCCGUACCAGGUAGCAUAAUGCGAGCAAUGUCGUACGAUUCAUAG -> MLRSSHLALWLGCVTSRTVSPVPGSIMRAMSYDS*
edc65
quelle
Gute Idee! Dachte nur daran, das zu tun. Du warst schneller als ich!
Optimierer
8

C, 190 Bytes (Funktion)

f(char*x){int a=0,i=0,j=0,s=1;for(;x[i];i%3||(s-=(x[j++]=a-37?a-9?"KNRSIITTEDGGVVAA*Y*CLFSSQHRRLLPP"[a/2]:77:87)==42,x[j]=a=0))a=a*4+(-x[i++]/2&3);puts(*x-77||i%3||s||x[j-1]-42?"Error":x);}

199 bis 194 Bytes (Programm)

a,i,j;char x[999];main(s){for(gets(x);x[i];i%3||(s-=(x[j++]=a-37?a-9?"KNRSIITTEDGGVVAA*Y*CLFSSQHRRLLPP"[a/2]:77:87)==42,x[j]=a=0))a=a*4+(-x[i++]/2&3);puts((*x-77||i%3||s||x[j-1]-42)?"Error":x);}

Ein paar Bytes gespart durch Verbesserung der Hash-Formel.

Hier ist ein lustiger Testfall:

AUGUAUCAUGAGCUCCUUCAGUGGCAAAGACUUGACUGA --> MYHELLQWQRLD* 

Erläuterung

Das Triplett von Buchstaben wird in eine Zahl zur Basis 4 umgewandelt. Jeder Buchstabe ist wie folgt gehasht.

x[i]       ASCII code       Hashed to (-x[i]/2&3) 
A        64+ 1  1000001            00   
G        64+ 7  1000111            01
U        64+21  1010101            10   
C        64+ 3  1000011            11

Dies gibt eine Zahl im Bereich 0..63. Die Idee ist nun, eine Lookup-Tabelle zu verwenden, die der von edc65 und Optimizer verwendeten ähnelt. Der Hash ist jedoch so ausgelegt, dass G und A nebeneinander liegen und U und C nebeneinander liegen.

Schauen Sie sich die Tabelle unter https://en.wikipedia.org/wiki/Genetic_code#RNA_codon_table an , dass bei den auf diese Weise geordneten Buchstaben im Allgemeinen das letzte Bit ignoriert werden kann. Mit Ausnahme von zwei Sonderfällen wird nur eine 32-stellige Nachschlagetabelle benötigt.

Siehe unten die ersten beiden Buchstaben und die entsprechenden Aminosäuren (wobei der dritte Buchstabe G / A und der dritte Buchstabe U / C ist). Korrekturen für die beiden Sonderfälle, die nicht in die 32-stellige Tabelle passen, sind fest codiert.

     A/G U/C          A/G U/C            A/G U/C         A/G U/C  
AAX> K   N       AGX> R   S         AUX> I   I      ACX> T   T
GAX> E   D       GGX> G   G         GUX> V   V      GCX> A   A
UAX> *   Y       UGX> *   C         UUX> L   F      UCX> S   S
CAX> Q   H       CGX> R   R         CUX> L   L      CCX> P   P

Corrections for special cases (where last bit cannot be ignored)
AUG 001001=9 -->  M
UGG 100101=37-->  W

Kommentierter Code

In der Golfversion befindet sich der i%3Code in der inkrementellen Position der forKlammer, wird jedoch im kommentierten Code in eine besser lesbare Position verschoben.

a,i,j;char x[999];                                                             //Array x used for storing both input and output. i=input pointer, j=output pointer.
main(s){                                                                       //s is commandline string count. if no arguments, will be set to zero. Will be used to count stops.
  for(gets(x);x[i];)                                                           //Get a string, loop until end of string (zero byte) found
    a=a*4+(-x[i++]/2&3),                                                       //Hash character x[i] to a number 0-3. leftshift any value already in a and add the new value. Increment i.
    i%3||(                                                                     //if i divisible by 3,
      s-=(x[j++]=a-37?a-9?"KNRSIITTEDGGVVAA*Y*CLFSSQHRRLLPP"[a/2]:77:87)==42,  //lookup the correct value in the table. for special cases a=24 and a=32 map to 'M' and 'W' (ASCII 77 and 87). If character is '*' (ASCII42) decrement s.   
      x[j]=a=0                                                                 //reset a to 0. clear x[j] to terminate output string.                                                     
    );   
  puts((*x-77||i%3||s||x[j-1]-42)?"Error":x);                                  //if first character not M or i not divisible by 3 or number of stops not 1 or last character not * print "Error" else print amino acid chain.
}
Level River St
quelle
Wenn es nur eine gäbe O! Ich habe jedoch einen Testfall hinzugefügt MGENETICS*, da dies das thematischste Wort ist, das ich machen kann: P
Sp3000
6

CJam, 317 121 104 Bytes

q3/{{"ACGU"#}%4b"KN T RS IIMI QH P R L ED A G V *Y S *CWC LF"S/{_,4\/*}%s=}%_('M=\)'*=\'*/,1=**\"Error"?

Dies kann noch weiter golfen werden.

Aktualisiert den Abbildungsmechanismus der in edc65 Antwort verwendet. Obwohl ich es mir selbst ausgedacht habe, hat er mich geschlagen :)

UPDATE : Verkürzt die Codon-Tabelle durch Beobachtung des Musters.

Probieren Sie es hier online aus

Optimierer
quelle
Dies bricht ab, wenn die Eingabe eine leere Zeichenfolge ist.
Peter Taylor
@PeterTaylor Eine Regel, die zu Ihrem Vorschlag hinzugefügt wurde, nachdem die Antwort gepostet wurde;). Ich werde den Code bald aktualisieren.
Optimierer
1
Es wurde keine Regel hinzugefügt, sondern ein Testfall, der von den Regeln bereits implizit gefordert wurde.
Peter Taylor
3

GolfScript (103 Bytes)

{)7&2/}%3/{4base'GGEDAAVVRSKNTTMIRRQHPPLLWC*YSSLF'{..'MW'?'I*'@),+=}%=}%''+.'*'/(1<'M'=*['']=*'Error'or

Online-Demo (Hinweis: Die beiden größten Testfälle sind nicht enthalten, da sie in 15 Sekunden ausgeführt werden müssen.)

Präparation

Wie Steve Verrill im Sandkasten betonte, kann die Nachschlagetabelle auf 32 Elemente plus zwei Sonderfälle reduziert werden. Es stellt sich heraus , dass die Sonderfälle sowohl beinhalten Zeichen ( Mund Wjeweils) , die nur einmal auftreten, und mit der richtigen Zuordnung der Zeichen zu Basis 4 Stellen ist es möglich , die volle 64-Element - Lookup - Tabelle aus den 32 Elementen aufzubauen , indem sie ein Duplikat zu tun -und- tr:

'GGEDAAVVRSKNTTMIRRQHPPLLWC*YSSLF'  # 32-element lookup table
{                                   # Map over the 32 elements...
  .                                 #   Duplicate the element
  .'MW'?'I*'@),+=                   #   Apply tr/MW/I*/ to the duplicate
}%

Sobald wir die Dekodierung durchgeführt haben, ermöglicht die Validierung viele Ansätze. Der kürzeste, den ich gefunden habe, ist

.'*'/       # Duplicate and split the copy around '*' retaining empty strings
(1<'M'=*    # Pull out the first string from the split (guarantee to exist even if input is
            # the empty string); if it starts with 'M' leave the rest of the split intact;
            # otherwise reduce it to the empty array
['']=       # Check whether we have ['']. If so, the split produced [prefix ''] where
            # prefix begins with 'M'. Otherwise we want an error.
*           # If we have an error case, reduce the original decoded string to ''
'Error'or   # Standard fallback mechanism
Peter Taylor
quelle
1 Byte. Herausforderung angenommen!
Optimierer
@Optimizer, eine direkte Übersetzung in CJam, spart einige Bytes, da es viele relevante eingebaute Funktionen gibt.
Peter Taylor
Meine Hashing-Funktion ist 57 Bytes lang, während Ihre 52 ist. Also kann ich nur maximal 5 Bytes speichern sehen ...
Optimizer
Ich bin froh, dass mein Kommentar im Sandkasten hilfreich war. Ich hoffte, dass es möglich sein könnte, die Tatsache, Mdie einer der Sonderfälle war, zu nutzen, um einen gültigen Start zu testen, aber das hat nicht geklappt. In dieser Zeichenfolge befinden sich noch 8 Paare identischer Buchstaben. Ich frage mich, ob sie als Kleinbuchstaben komprimiert werden können: g-->GG a-->AAusw. Wenn Dekomprimierung in weniger als 8 Zeichen erreicht werden kann, wäre es lohnenswert.
Level River St
1

Python, 473 Bytes

t={'U(A[AG]|GA)':'*','GC.':'A','UG[UC]':'C','GA[UC]':'D','GA[AG]':'E','UU[UC]':'F','GG.':'G','CA[UC]':'H','AU[UCA]':'I','AA[AG]':'K','(UU[AG]|CU.)':'L','AUG':'M','AA[UC]':'N','CC.':'P','CA[AG]':'Q','(CG.|AG[AG])':'R','(UC.|AG[UC])':'S','AC.':'T','GU.':'V','UGG':'W','UA[UC]':'Y'}
import re
i=raw_input()
a=''
for x in[i[y:y+3]for y in range(0,len(i),3)]:
 a+=[t[u]for u in t.keys()if re.match(u, x)][0]
print["Error",a][all((a[0]+a[-1]=="M*",len(i)%3==0,not"*"in a[1:-1]))]
James Williams
quelle
1

Python 2, 370 358 354 Bytes

Dies ist ein sehr einfacher Ansatz ohne Komprimierung, bei dem nur versucht wird, die Informationen ziemlich dicht zu packen:

s=lambda x:x and[x[:3]]+s(x[3:])or[]
def f(I):O=''.join(d*any(0==x.find(p)for p in e)for x in s(I)for d,e in zip('*ACDEFGHIKLMNPQRSTVWY',map(s,'UAAUAGUGA,GC,UGUUGC,GAUGAC,GAAGAG,UUUUUC,GG,CAUCAC,AUUAUCAUA,AAAAAG,UUAUUGCU,AUG,AAUAAC,CC,CAACAG,AGAAGGCG,AGUAGCUC,AC,GU,UGG,UAUUAC'.split(','))));return['Error',O][len(I)%3==0==len(O)-O.find('*')-(O[0]=='M')]

Bearbeiten: Einige Zeichen wurden auf Vorschlag von xnor abgeschabt.

Emil
quelle
Ich glaube, Sie können srekursiv als kürzer schreiben s=lambda x:x and[x[:3]]+s(x[3:]).
30.
@xnor Großartig, daran habe ich nicht gedacht. So funktioniert es nicht ganz, denn am Ende der Rekursion wird ein leerer String ausgegeben, keine leere Liste. Aber mit vier weiteren Charakteren kann ich es schaffen. Vielen Dank!
Emil
1

Scala (317 Zeichen)

def g(c:Char)="ACGU"indexOf c;def h(s:String,i:Int)=g(s(i))*16+g(s(i+1))*4+g(s(i+2));def p(a:Int)=a!=48&&a!=50&&a!=56;def f(s:String)=if(s.length%3!=0||h(s,0)!=14||p(h(s,s.length-3)))"Error"else{var r="";for(i<-0 to s.length-3 by 3)r+="KNKNTTTTRSRSIIMIQHQHPPPPRRRRLLLLEDEDAAAAGGGGVVVV*Y*YSSSS*CWCLFLF"charAt h(s,i);r}

Die Hauptfunktion ist f. Eine bessere Wahl wäre natürlich die Rückgabe von Option[String].

bb94
quelle
0

JavaScript (ES6), 143 Byte

s=>/^M\w*\*$/.test(s=s.replace(/.../g,c=>"PVLVLHDVLGRGRAPGR*KYNVL*KTSTSGRTSILIFYNMLR*SCTSRWEQDHIFEQPAPASC.A"[parseInt(c,36)%128%65]))?s:'Error'

Probieren Sie es online!

Arnauld
quelle