Трансляция РНК в белок

18

РНК , как и ДНК, представляет собой молекулу, обнаруженную в клетках, кодирующих генетическую информацию. Он состоит из нуклеотидов , которые представлены основаниями аденин (A), цитозин (C), гуанин (G) и урацил (U). * Кодон представляет собой последовательность из трех нуклеотидов.

Белки - это большие молекулы, которые выполняют широкий спектр функций, такие как кератин, который содержится в волосах и ногтях, и гемоглобин, который переносит кислород в клетках крови. Они состоят из аминокислот , которые кодируются в виде кодонов в молекулах РНК. Иногда разные кодоны могут кодировать одну и ту же аминокислоту. Каждая аминокислота обычно представлена ​​одной буквой, например, H обозначает гистидин.

Учитывая последовательность ACGU, можете ли вы перевести ее в соответствующую строку белка?

* ДНК состоит из ACGT, где T - тимин. Во время транскрипции ДНК в РНК тимин заменяется урацилом.


вход

Ввод будет одной строкой, состоящей только из символов ACGUв верхнем регистре. Вы можете написать либо функцию, либо полную программу для этой задачи.

Выход

Вы можете выбрать вывод через печать или возврат строки (последний вариант доступен только в случае функции).

Перевод следует начинать на старте - кодоне ( AUG, представлена в виде M) и конце в стопе - кодоне (один из UAA, UAGили UGA, представлен в виде *). В четырех случаях ввод может быть недействительным:

  • Ввод не начинается со стартового кодона
  • Ввод не заканчивается стоп-кодоном
  • Длина входа не кратна 3
  • Вход содержит кодон остановки где-то кроме конца

Во всех этих случаях Errorдолжны быть выведены. Обратите внимание, что, в отличие от стоп-кодонов, стартовые кодоны могут появляться после начала строки.

В противном случае вы должны преобразовать каждый кодон в соответствующую ему аминокислоту через следующую таблицу кодирования РНК :

* 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

... и вывести переведенную строку.

Примеры

Неверные случаи:

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

Допустимые случаи:

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

Изменить: Добавлено больше тестов

счет

Это код гольф, поэтому код в наименьшем количестве байтов выигрывает.

Примечание: я не специалист по молекулярной биологии, поэтому не стесняйтесь поправлять меня, если я что-то неверно уточнил :)

Sp3000
источник
1
Правильный переводчик должен найти открытую рамку для чтения в любой строке, а не только в тех, которые начинаются с AUG!
канадец
@canadianer Ahaha, да, я изначально подумал об этом, но я не хотел усложнять вопрос, вводя открытые рамки считывания (или даже переводя несколько белков из одной строки) :)
Sp3000
Пустая строка будет полезным контрольным примером, потому что она нарушит некоторые подходы для проверки того, что декодированная последовательность начинается Mи заканчивается *.
Питер Тейлор
@PeterTaylor Добавлено вместе с несколькими короткими тестовыми
примерами
1
Если вы хотите испытывать настоящую боль, вы можете использовать ДНК вместо РНК, поэтому у вас тоже есть рамки для чтения назад.
user137

Ответы:

6

CJam ( 97 93 92 91 байт)

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

Это порт моего решения GolfScript с немного подправленной хэш-функцией, потому что, к моему удивлению, CJam не позаимствовал у GolfScript обработку строк как массивов целых чисел.

6 байтов сэкономлено благодаря предложениям от Оптимизатора (включая два байта из того, что я думал, что попробовал и не сработало - ага).

Питер Тейлор
источник
1
q"GACU"f#3/{4b"GGEDAAVVRSKNTTMIRRQHPPLLWC*YSSLF"{_s"MW""I*"er}%=}%s_'*/(1<"M"=*Q="Error"@?- 90
Оптимизатор
@ Оптимизатор, кое-что из этого кажется улучшением. Тем не менее, это дает ошибку во время выполнения, и сравнение, Qа не [Q]просто неверно.
Питер Тейлор
1. вы неправильно скопировали код, когда код занимает несколько строк в комментариях, он получает странный символ юникода при разрыве строки. Затем вам придется вручную ввести код. 2. См. Логику, она была изменена, чтобы правильно работать, таким образом, [Q]чтобы Qизменить это правильно.
Оптимизатор
@ Оптимизатор, попробуйте тестовый примерAUGUAGUGA
Питер Тейлор,
1
Ах хорошо. Все еще [Q]->Qa
Оптимизатор
10

JavaScript (ES6) 167 177 символов, закодированных в UTF8 как 167 177 байтов

... так что я надеюсь, что все счастливы.

Редактировать На самом деле, нет необходимости в специальном случае, если последний блок слишком короткий. Если последние 2 (или 1) символа не отображаются, результирующая строка не заканчивается на «*», и это в любом случае выдает ошибку.

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'

Разъяснения

Каждый символ в триплете может иметь 4 значения, поэтому существует ровно 4 ^ 3 == 64 триплета. Функция C отображает каждый триплет на число от 0 до 63. Проверка ошибок не требуется, поскольку входные символы являются только ACGU.

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

Каждый триплет отображается на аминокислоту, идентифицированную одним символом. Мы можем закодировать это в 64-символьную строку. Чтобы получить строку, начните с карты кодонов:

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

... получение "KNKNTTTTRSRSIIMIQHQHPPPPRRRRLLLLEDEDAAAAGGGGVVVV * Y * YSSSS * CWCLFLF"

Таким образом, мы можем отсканировать входную строку и использовать ту же логику функции C, чтобы получить код 0..63 и из кода символ аминокислоты. Функция замены будет разбивать входную строку на 3 блока символов, в конечном счете оставляя 1 или 2 символа неуправляемыми (что приведет к недопустимой строке результата, не заканчивающейся на «*»).

Наконец, проверьте правильность закодированной строки с помощью регулярного выражения: она должна начинаться с «M», не должна содержать «*» и заканчиваться «*»

Тест в консоли FireBug / FireFox

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

Выход

AUGCUAG -> Error
GGGCACUAG -> Error
AUGAACGGA -> Error
AUGUAGUGA -> Error
AAAAAAA -> Error
AUGUUUGUUCCGUCGAAAUACCUAUGAACACGCUAA -> Error
AUGAGGUGUAGCUGA -> MRCS*
AUGCCAGUCGCACGAUUAGUUCACACGCUCUUGUAA -> MPVARLVHTLL*
AUGCUGCGGUCCUCGCAUCUAGCGUUGUGGUUAGGGUGUGUAACUUCGAGAACAGUGAGUCCCGUACCAGGUAGCAUAAUGCGAGCAAUGUCGUACGAUUCAUAG -> MLRSSHLALWLGCVTSRTVSPVPGSIMRAMSYDS*
edc65
источник
Хорошая идея! Просто думал об этом. Ты подтолкнул меня на это!
Оптимизатор
8

C 190 байт (функция)

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 байта (программа)

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

Сохранено несколько байтов за счет улучшения формулы хэша.

Вот забавный тестовый пример:

AUGUAUCAUGAGCUCCUUCAGUGGCAAAGACUUGACUGA --> MYHELLQWQRLD* 

объяснение

Тройка букв преобразуется в основную цифру 4. Каждое письмо хэшируется следующим образом.

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

Это дает число в диапазоне 0..63. Идея теперь состоит в том, чтобы использовать справочную таблицу, аналогичную тем, которые используются edc65 и Optimizer. Однако хэш разработан так, что G и A находятся рядом друг с другом, а U и C находятся рядом друг с другом.

Глядя на таблицу по адресу https://en.wikipedia.org/wiki/Genetic_code#RNA_codon_table , мы видим, что с буквами, упорядоченными таким образом, обычно последний бит можно игнорировать. Требуется только таблица поиска из 32 символов, за исключением двух особых случаев.

См. Ниже первые две буквы и соответствующие аминокислоты (где 3-я буква - G / A, а где 3-я буква - U / C). Исправления для двух особых случаев, которые не соответствуют 32-символьной таблице, жестко закодированы.

     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

Код комментария

В версии для игры в гольф i%3код находится в увеличенной позиции forскобки, но он перемещается в более читаемую позицию в закомментированном коде.

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.
}
Уровень реки St
источник
Если бы только был O! Я добавил тестовый пример MGENETICS*, потому что это самое тематическое слово, которое я мог
произнести
6

CJam, 317 121 104 байта

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

Это все еще может быть в гольфе дальше.

Обновлен механизм отображения на тот, который использовался в ответе edc65. Несмотря на то, что я придумал это сам, он победил меня в этом :)

ОБНОВИТЬ : Сократил карту таблицы кодонов, наблюдая образец в ней.

Попробуйте это онлайн здесь

оптимизатор
источник
Это прерывается, если вход является пустой строкой.
Питер Тейлор
@PeterTaylor Правило, которое было добавлено в ваше предложение после того, как ответ был опубликован;). Я скоро обновлю код.
Оптимизатор
1
Это было не правило, которое было добавлено, это был тестовый пример, который уже неявно требовался правилами.
Питер Тейлор
3

GolfScript (103 байта)

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

Онлайн демо (NB не включает два самых больших тестовых случая, потому что он должен быть запущен за 15 секунд).

рассечение

Как указал Стив Веррилл в песочнице, справочную таблицу можно уменьшить до 32 элементов плюс два особых случая. Оказывается, что в особых случаях используются символы ( Mи Wсоответственно), которые встречаются только один раз, и при правильном сопоставлении символов с четырьмя основными цифрами можно построить полную 64-элементную таблицу поиска из 32 элементов, выполнив дубликат. -и- tr:

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

Затем, после того как мы выполнили декодирование, проверка допускает множество подходов. Самое короткое, что я нашел, это

.'*'/       # 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
Питер Тейлор
источник
1 байт Вызов принят!
Оптимизатор
@Optimizer, прямой перевод на CJam сэкономит несколько байтов, потому что в нем много соответствующих встроенных модулей.
Питер Тейлор
Моя функция хеширования имеет длину 57 байт, а ваша - 52. Таким образом, я вижу не более 5 байт сохраняющих ...
Optimizer
Я рад, что мой комментарий в песочнице был полезен. Я надеялся, что можно будет использовать тот факт, что это Mбыл один из особых случаев, чтобы проверить правильность старта, но это не сработало. В этой строке еще 8 пар одинаковых букв. Интересно, могут ли они быть сжаты строчными буквами g-->GG a-->AAи т. Д. Если декомпрессия может быть выполнена до 8 символов, это будет целесообразно.
Уровень Река St
1

Python, 473 байта

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]))]
Джеймс Уильямс
источник
1

Python 2, 370 358 354 байта

Это очень простой подход без сжатия, просто попытка упаковать информацию довольно плотно:

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

Изменить: сбрил несколько символов в соответствии с предложением xnor.

Эмиль
источник
Я считаю, что вы можете написать sкороче как s=lambda x:x and[x[:3]]+s(x[3:]).
xnor
@xnor Отлично, я не думал об этом. Это не совсем так, потому что в конце рекурсии будет выведена пустая строка, а не пустой список. Но с еще четырьмя персонажами я могу заставить его работать. Благодарность!
Эмиль
1

Скала (317 символов)

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}

Основная функция есть f. Конечно, лучшим выбором будет вернуть Option[String].

bb94
источник