Tłumaczenie RNA na białka

18

RNA , podobnie jak DNA, jest cząsteczką występującą w komórkach kodujących informację genetyczną. Składa się z nukleotydów , które są reprezentowane przez zasady adeniny (A), cytozyny (C), guaniny (G) i uracylu (U). * Kodon to sekwencja trzech nukleotydów.

Białka to duże cząsteczki, które spełniają szeroki wachlarz funkcji, takich jak keratyna występująca we włosach i paznokciach oraz hemoglobina przenosząca tlen w komórkach krwi. Składają się z aminokwasów , które są kodowane jako kodony w cząsteczkach RNA. Czasami różne kodony mogą kodować ten sam aminokwas. Każdy aminokwas jest zwykle reprezentowany przez jedną literę, na przykład H oznacza histydynę.

Biorąc pod uwagę sekwencję ACGU, czy możesz przetłumaczyć go na odpowiedni ciąg białka?

* DNA składa się z ACGT, gdzie T oznacza tyminę. Podczas transkrypcji DNA na RNA tyminę zastępuje się uracylem.


Wejście

Dane wejściowe będą pojedynczym ciągiem znaków składającym się wyłącznie z ACGUwielkich liter. Możesz napisać funkcję lub pełny program dla tego wyzwania.

Wynik

Możesz wybrać wyjście poprzez wydrukowanie lub zwrócenie ciągu (ten ostatni wybór jest dostępny tylko w przypadku funkcji).

Tłumaczenie powinno rozpoczynać się od kodonu startu ( AUG, reprezentowane M) i na końcu w kodon stop (jeden UAA, UAGlub UGA, reprezentowane *). Istnieją cztery przypadki, w których dane wejściowe mogą być nieprawidłowe:

  • Wejście nie zaczyna się od kodonu start
  • Wejście nie kończy się kodonem stop
  • Długość wejścia nie jest wielokrotnością 3
  • Dane wejściowe zawierają kodon stop w innym miejscu niż na końcu

We wszystkich tych przypadkach Errorpowinny być generowane. Zauważ, że w przeciwieństwie do kodonów stop, kodony start mogą pojawić się po rozpoczęciu łańcucha.

W przeciwnym razie należy przekonwertować każdy kodon na odpowiedni aminokwas za pomocą następującej tabeli kodonów RNA :

* 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

... i wyślij przetłumaczony ciąg.

Przykłady

Nieprawidłowe przypadki:

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

Ważne przypadki:

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

Edycja: Dodano więcej przypadków testowych

Punktacja

To jest kod golfowy, więc kod w najmniejszej liczbie bajtów wygrywa.

Uwaga: nie jestem ekspertem w dziedzinie biologii molekularnej, więc możesz mnie poprawić, jeśli coś źle przedstawiłem :)

Sp3000
źródło
1
Właściwy tłumacz powinien być w stanie znaleźć otwartą ramkę odczytu w dowolnym ciągu, nie tylko w tych, które zaczynają się od AUG!
kanadyjczyk
@canadianer Ahaha tak, początkowo to rozważałem, ale nie chciałem, aby pytanie było zbyt skomplikowane poprzez wprowadzenie otwartych ramek do czytania (lub nawet tłumaczenie wielu białek z jednego ciągu) :)
Sp3000
Pusty ciąg znaków byłby przydatnym przypadkiem testowym, ponieważ przerwie on niektóre podejścia do testowania, od którego zaczyna się Mi kończy dekodowana sekwencja *.
Peter Taylor,
@PeterTaylor Dodano, wraz z kilkoma krótkimi przypadkami testowymi :)
Sp3000
1
Jeśli chcesz być prawdziwym bólem, możesz użyć DNA zamiast RNA, więc masz także ramki do czytania wstecz.
użytkownik137

Odpowiedzi:

6

CJam ( 97 93 92 91 bajtów)

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

Jest to część mojego rozwiązania GolfScript z nieco poprawioną funkcją skrótu, ponieważ ku mojemu zdziwieniu jedną rzeczą, której CJam nie pożyczył od GolfScript, traktuje łańcuchy znaków jako tablice liczb całkowitych.

6 bajtów zapisanych dzięki sugestiom Optimizera (w tym dwa bajty z czegoś, co myślałem, że próbowałem i nie działało - huh).

Peter Taylor
źródło
1
q"GACU"f#3/{4b"GGEDAAVVRSKNTTMIRRQHPPLLWC*YSSLF"{_s"MW""I*"er}%=}%s_'*/(1<"M"=*Q="Error"@?- 90
Optymalizator
@Optimizer, niektóre z nich wydają się być poprawą. Daje to jednak błąd w czasie wykonywania, a porównanie Qraczej niż [Q]jest po prostu niepoprawne.
Peter Taylor,
1. kod nie został poprawnie skopiowany, gdy kod obejmuje wiele linii w komentarzach, na końcu wiersza pojawia się dziwny znak Unicode. Musisz wtedy ręcznie wpisać kod. 2. Patrz logikę, to został zmieniony działał poprawnie, a tym samym [Q]do Qzmiany jest prawidłowe.
Optymalizator
@Optimizer, wypróbuj test caseAUGUAGUGA
Peter Taylor
1
Ah, dobrze. Nadal [Q]->Qa
Optymalizator
10

JavaScript (ES6) 167 177 znaków zakodowanych w UTF8 jako 167 177 bajtów

... więc mam nadzieję, że wszyscy są szczęśliwi.

Edytuj W rzeczywistości nie ma potrzeby specjalnego przypadku dla ostatniego bloku za krótko. Jeśli ostatnie 2 (lub 1) znaki nie są zamapowane, łańcuch wynikowy nie kończy się na „*”, co i tak daje błąd.

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'

Wyjaśniono

Każdy znak w triplecie może mieć 4 wartości, więc są dokładnie 4 ^ 3 == 64 trojaczki. Funkcja C odwzorowuje każdą trojkę na liczbę od 0 do 63. Nie trzeba sprawdzać błędów, ponieważ znaki wejściowe to tylko ACGU.

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

Każda trójka mapuje się do aminokwasu zidentyfikowanego przez pojedynczy znak. Możemy zakodować to w ciągu 64 znaków. Aby uzyskać ciąg, zacznij od mapy kodonów:

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

... uzyskanie „KNKNTTTTRSRSIIMIQHQHPPPPRRRRLLLLEDEDAAAAGGGGVVVV * Y * YSSSS * CWCLFLF”

Możemy więc zeskanować ciąg wejściowy i użyć tej samej logiki funkcji C, aby uzyskać kod 0..63, a z kodu kod aminokwasowy. Funkcja zamiany podzieli łańcuch wejściowy na 3 bloki znaków, ostatecznie pozostawiając 1 lub 2 znaki niezarządzane (co da niepoprawny ciąg wyników, nie kończący się na „*”).

Na koniec sprawdź, czy zakodowany ciąg jest prawidłowy, używając wyrażenia regularnego: musi zaczynać się od „M”, nie może zawierać „*” i musi kończyć się na „*”

Testuj w konsoli FireBug / FireFox

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

Wynik

AUGCUAG -> Error
GGGCACUAG -> Error
AUGAACGGA -> Error
AUGUAGUGA -> Error
AAAAAAA -> Error
AUGUUUGUUCCGUCGAAAUACCUAUGAACACGCUAA -> Error
AUGAGGUGUAGCUGA -> MRCS*
AUGCCAGUCGCACGAUUAGUUCACACGCUCUUGUAA -> MPVARLVHTLL*
AUGCUGCGGUCCUCGCAUCUAGCGUUGUGGUUAGGGUGUGUAACUUCGAGAACAGUGAGUCCCGUACCAGGUAGCAUAAUGCGAGCAAUGUCGUACGAUUCAUAG -> MLRSSHLALWLGCVTSRTVSPVPGSIMRAMSYDS*
edc65
źródło
Dobry pomysł! Właśnie myślałem o zrobieniu tego. Pobiłeś mnie do tego!
Optymalizator
8

C, 190 bajtów (funkcja)

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 194 bajtów (program)

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

Zaoszczędzono kilka bajtów, poprawiając formułę mieszania.

Oto zabawny przypadek testowy:

AUGUAUCAUGAGCUCCUUCAGUGGCAAAGACUUGACUGA --> MYHELLQWQRLD* 

Wyjaśnienie

Trójka liter jest konwertowana na podstawową liczbę 4. Każda litera jest mieszana w następujący sposób.

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

Daje to liczbę z zakresu 0..63 . Chodzi teraz o użycie tabeli odnośników podobnej do tabeli używanej przez edc65 i Optimizer. Jednak skrót jest tak zaprojektowany, że G i A znajdują się obok siebie, a U i C są obok siebie.

Patrząc na stół na https://en.wikipedia.org/wiki/Genetic_code#RNA_codon_table , widzimy, że przy literach uporządkowanych w ten sposób, na ogół ostatni bit można zignorować. Potrzebna jest tylko 32-znakowa tabela odnośników, z wyjątkiem dwóch specjalnych przypadków.

Zobacz poniżej dwie pierwsze litery i odpowiadające im aminokwasy (gdzie trzecia litera to G / A, a trzecia litera to U / C). Korekty dla dwóch specjalnych przypadków, które nie pasują do 32-znakowej tabeli, są zakodowane na stałe.

     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

Skomentowany kod

W wersji golfowej i%3kod znajduje się w pozycji przyrostowej fornawiasu, ale jest przenoszony do bardziej czytelnej pozycji w skomentowanym kodzie.

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
źródło
Gdyby tylko był O! Dodałem jednak przypadek testowy MGENETICS*, ponieważ jest to najbardziej tematyczne słowo, jakie mogę
napisać
6

CJam, 317 121 104 bajtów

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"?

Można to jeszcze pograć w golfa.

Zaktualizowano mechanizm mapowania do tego zastosowanego w odpowiedzi edc65. Mimo że sam to wymyśliłem, pobił mnie do tego :)

AKTUALIZACJA : Skrócono mapę tabeli kodonów, obserwując w niej wzorzec.

Wypróbuj online tutaj

Optymalizator
źródło
Dzieje się tak, jeśli wejście jest pustym ciągiem.
Peter Taylor,
@PeterTaylor Reguła, która została dodana do Twojej sugestii po opublikowaniu odpowiedzi;). Wkrótce zaktualizuję kod.
Optymalizator
1
Nie była to dodana reguła, tylko przypadek testowy, który był już domyślnie wymagany przez reguły.
Peter Taylor,
3

GolfScript (103 bajty)

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

Demo online (NB nie obejmuje dwóch największych przypadków testowych, ponieważ musi zostać uruchomiony w 15 sekund).

Sekcja

Jak zauważył Steve Verrill w piaskownicy, tabelę wyszukiwania można zredukować do 32 elementów plus dwa specjalne przypadki. Okazuje się, że przypadki szczególne dotyczą zarówno znaków ( Mi Wodpowiednio), które występują tylko raz, a przy odpowiednim odwzorowaniu znaków na 4 cyfry możliwe jest zbudowanie pełnej 64-elementowej tabeli odnośników z 32 elementów poprzez wykonanie duplikatu i tr:

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

Po zakończeniu dekodowania weryfikacja pozwala na wiele podejść. Najkrótszy, jaki znalazłem, to

.'*'/       # 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
źródło
1 bajt. Wyzwanie przyjęte!
Optymalizator
@Optimizer, proste tłumaczenie na CJam pozwoli zaoszczędzić kilka dobrych bajtów, ponieważ ma wiele odpowiednich wbudowanych funkcji.
Peter Taylor,
Moja funkcja haszująca ma 57 bajtów, a twoja 52. Więc widzę tylko najwyżej 5 bajtów oszczędzających ...
Optymalizator
Cieszę się, że mój komentarz w piaskownicy był przydatny. Miałem nadzieję, że możliwe będzie wykorzystanie faktu, że Mbył to jeden ze specjalnych przypadków, w celu przetestowania prawidłowego startu, ale tak się nie udało. Ciąg zawiera jeszcze 8 par identycznych liter. Zastanawiam się, czy można je skompresować małymi literami: g-->GG a-->AAitp. Jeśli dekompresję można uzyskać przy użyciu mniej niż 8 znaków, warto.
Level River St
1

Python, 473 bajty

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
źródło
1

Python 2, 370 358 354 bajtów

Jest to bardzo proste podejście bez kompresji, po prostu próbujące spakować informacje dość gęsto:

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

Edycja: Ogoliłem kilka znaków zgodnie z sugestią Xnora.

Emil
źródło
Wierzę, że można srekurencyjnie pisać krótsze jako s=lambda x:x and[x[:3]]+s(x[3:]).
xnor
@xnor Świetnie, nie myślałem o tym. Nie działa tak do końca, ponieważ pod koniec rekurencji wyświetli pusty ciąg, a nie pustą listę. Ale z czterema dodatkowymi postaciami mogę sprawić, by działało. Dzięki!
Emil
1

Scala (317 znaków)

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}

Główną funkcją jest f. Oczywiście lepszym wyborem byłby zwrot Option[String].

bb94
źródło
0

JavaScript (ES6), 143 bajty

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

Wypróbuj online!

Arnauld
źródło