RNA can be broken into three nucleotide sequences called codons, and then translated to a polypeptide like so:
RNA:
"AUGUUUUCU"
=> translates toCodons:
"AUG", "UUU", "UCU"
=> which become a polypeptide with the following sequence =>Protein:
"Methionine", "Phenylalanine", "Serine"
There are 64 codons which in turn correspond to 20 amino acids; however, all of the codon sequences and resulting amino acids are not important in this exercise. If it works for one codon, the program should work for all of them. However, feel free to expand the list in the test suite to include them all.
There are also three terminating codons (also known as 'STOP' codons); if any of these codons are encountered (by the ribosome), all translation ends and the protein is terminated.
All subsequent codons after are ignored, like this:
RNA:
"AUGUUUUCUUAAAUG"
=>Codons:
"AUG", "UUU", "UCU", "UAA", "AUG"
=>Protein:
"Methionine", "Phenylalanine", "Serine"
Note the stop codon
"UAA"
terminates the translation and the final methionine is not translated into the protein sequence.Learn more about protein translation on Wikipedia
This was the task given. I originally did this some time ago in Python 3.
def proteins(strand):
sub_len = 3
split_str = [strand[i:i+sub_len] for i in range(0, len(strand), sub_len)]
protein = []
for x in split_str:
if x == "UAA" or x == "UAG" or x == "UGA":
break
elif x == "AUG":
protein.append("Methionine")
elif x == "UUU" or x == "UUC":
protein.append("Phenylalanine")
elif x == "UUA" or x == "UUG":
protein.append("Leucine")
elif x == "UCU" or x == "UCC" or x == "UCA" or x == "UCG":
protein.append("Serine")
elif x == "UAU" or x == "UAC":
protein.append("Tyrosine")
elif x == "UGU" or x == "UGC":
protein.append("Cysteine")
elif x == "UGG":
protein.append("Tryptophan")
return protein
This time I did this in C#.
// This file was auto-generated based on version 1.1.1 of the canonical data.
using System;
using System.Collections.Generic;
using System.Linq;
public static class ProteinTranslation
{
public static string[] Proteins(string strand)
{
// Create a list to house codons
List<string> protein = new List<string>();
// Convert string(RNA aka strand) to Array so we can iterate in chunks of 3's(codons)
IEnumerable<string> output = RnaToCodons(strand);
// Add codons to list and return results
return Codons(protein, output);
}
private static IEnumerable<string> RnaToCodons(string strand, int k = 0) => strand.ToLookup(c => Math.Floor(k++ / (double)3)).Select(e => new String(e.ToArray()));
private static string[] Codons(List<string> protein, IEnumerable<string> output)
{
foreach (var item in output)
{
switch (item)
{
case "UAA": case "UAG": case "UGA": return protein.ToArray();
case "UCU": case "UCC": case "UCA": case "UCG": protein.Add("Serine"); break;
case "UUU": case "UUC": protein.Add("Phenylalanine"); break;
case "UUA": case "UUG": protein.Add("Leucine"); break;
case "UAU": case "UAC": protein.Add("Tyrosine"); break;
case "UGU": case "UGC": protein.Add("Cysteine"); break;
case "UGG": protein.Add("Tryptophan"); break;
case "AUG": protein.Add("Methionine"); break;
}
}
return protein.ToArray();
}
}
Requiring me to pass these test.
// This file was auto-generated based on version 1.1.1 of the canonical data.
using Xunit;
public class ProteinTranslationTests
{
[Fact]
public void Methionine_rna_sequence() => Assert.Equal(new[] { "Methionine" }, ProteinTranslation.Proteins("AUG"));
[Fact]
public void Phenylalanine_rna_sequence_1() => Assert.Equal(new[] { "Phenylalanine" }, ProteinTranslation.Proteins("UUU"));
[Fact]
public void Phenylalanine_rna_sequence_2() => Assert.Equal(new[] { "Phenylalanine" }, ProteinTranslation.Proteins("UUC"));
[Fact]
public void Leucine_rna_sequence_1() => Assert.Equal(new[] { "Leucine" }, ProteinTranslation.Proteins("UUA"));
[Fact]
public void Leucine_rna_sequence_2() => Assert.Equal(new[] { "Leucine" }, ProteinTranslation.Proteins("UUG"));
[Fact]
public void Serine_rna_sequence_1() => Assert.Equal(new[] { "Serine" }, ProteinTranslation.Proteins("UCU"));
[Fact]
public void Serine_rna_sequence_2() => Assert.Equal(new[] { "Serine" }, ProteinTranslation.Proteins("UCC"));
[Fact]
public void Serine_rna_sequence_3() => Assert.Equal(new[] { "Serine" }, ProteinTranslation.Proteins("UCA"));
[Fact]
public void Serine_rna_sequence_4() => Assert.Equal(new[] { "Serine" }, ProteinTranslation.Proteins("UCG"));
[Fact]
public void Tyrosine_rna_sequence_1() => Assert.Equal(new[] { "Tyrosine" }, ProteinTranslation.Proteins("UAU"));
[Fact]
public void Tyrosine_rna_sequence_2() => Assert.Equal(new[] { "Tyrosine" }, ProteinTranslation.Proteins("UAC"));
[Fact]
public void Cysteine_rna_sequence_1() => Assert.Equal(new[] { "Cysteine" }, ProteinTranslation.Proteins("UGU"));
[Fact]
public void Cysteine_rna_sequence_2() => Assert.Equal(new[] { "Cysteine" }, ProteinTranslation.Proteins("UGC"));
[Fact]
public void Tryptophan_rna_sequence() => Assert.Equal(new[] { "Tryptophan" }, ProteinTranslation.Proteins("UGG"));
[Fact]
public void Stop_codon_rna_sequence_1() => Assert.Empty(ProteinTranslation.Proteins("UAA"));
[Fact]
public void Stop_codon_rna_sequence_2() => Assert.Empty(ProteinTranslation.Proteins("UAG"));
[Fact]
public void Stop_codon_rna_sequence_3() => Assert.Empty(ProteinTranslation.Proteins("UGA"));
[Fact]
public void Translate_rna_strand_into_correct_protein_list() => Assert.Equal(new[] { "Methionine", "Phenylalanine", "Tryptophan" }, ProteinTranslation.Proteins("AUGUUUUGG"));
[Fact]
public void Translation_stops_if_stop_codon_at_beginning_of_sequence() => Assert.Empty(ProteinTranslation.Proteins("UAGUGG"));
[Fact]
public void Translation_stops_if_stop_codon_at_end_of_two_codon_sequence() => Assert.Equal(new[] { "Tryptophan" }, ProteinTranslation.Proteins("UGGUAG"));
[Fact]
public void Translation_stops_if_stop_codon_at_end_of_three_codon_sequence() => Assert.Equal(new[] { "Methionine", "Phenylalanine" }, ProteinTranslation.Proteins("AUGUUUUAA"));
[Fact]
public void Translation_stops_if_stop_codon_in_middle_of_three_codon_sequence() => Assert.Equal(new[] { "Tryptophan" }, ProteinTranslation.Proteins("UGGUAGUGG"));
[Fact]
public void Translation_stops_if_stop_codon_in_middle_of_six_codon_sequence() => Assert.Equal(new[] { "Tryptophan", "Cysteine", "Tyrosine" }, ProteinTranslation.Proteins("UGGUGUUAUUAAUGGUUU"));
}
I had issues on deciding how to iterate a string with Nth length of a substring. split_str and RnaToCodons was code I borrowed from post on StackOverflow. I'm not sure, but I have a feeling that a better way to do this exist. In C#, I wanted to decouple my code unlike the Python version I made. I wanted to make sure I only made one pass through the given string with Codons. Not sure if the switch case was the best way to go here, but in my opinion its easy to read.
It will be interesting to see if this can be sped up or more concise while still be readable along with learning if there is a better way to iterate a string with a substring.