Skip to content

Commit

Permalink
Merge pull request #305 from go717franciswang/protein-translation
Browse files Browse the repository at this point in the history
Protein translation (fix #267)
  • Loading branch information
petertseng authored Jun 18, 2017
2 parents a59a6fa + 957079c commit 772d684
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 58 deletions.
33 changes: 11 additions & 22 deletions exercises/protein-translation/example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,18 @@ pub fn parse<'a>(pairs: Vec<(&'a str, &'a str)>) -> CodonInfo<'a> {

impl<'a> CodonInfo<'a> {
pub fn name_for(&self, codon: &str) -> Result<&'a str, &'static str> {
if codon.len() != 3 {
return Err("invalid length")
}

let mut valid = true;
let lookup: String = codon.chars().map(|l| {
// Get an example of a "letter" represented by the possibly encoded letter.
// Since every codon represented by the compressed notation has to be of
// the desired amino acid just picking one at random will do.
match l {
'A' | 'W' | 'M' | 'R' | 'D' | 'H' | 'V' | 'N' => 'A',
'C' | 'S' | 'Y' | 'B' => 'C',
'G' | 'K' => 'G',
'T' => 'T',
_ => { valid = false; ' ' }
}
}).collect();
if !valid {
return Err("invalid char")
match self.actual_codons.get(&codon) {
Some(name) => Ok(name),
None => Err("Invalid")
}
}

// If the input table is correct (which it is) every valid codon is in it
// so unwrap() shouldn't panic.
Ok(self.actual_codons.get(&lookup.as_ref()).unwrap())
pub fn of_rna(&self, strand: &str) -> Result<Vec<&'a str>, &'static str> {
strand.chars()
.collect::<Vec<char>>()
.chunks(3)
.map(|chars| self.name_for(&chars.iter().collect::<String>()))
.take_while(|result| result.is_err() || result.unwrap() != "stop codon")
.collect()
}
}
92 changes: 56 additions & 36 deletions exercises/protein-translation/tests/proteins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,54 +3,44 @@ extern crate protein_translation as proteins;
#[test]
fn test_methionine() {
let info = proteins::parse(make_pairs());
assert_eq!(info.name_for("ATG"), Ok("methionine"));
assert_eq!(info.name_for("AUG"), Ok("methionine"));
}

#[test]
#[ignore]
fn test_cysteine_tgt() {
let info = proteins::parse(make_pairs());
assert_eq!(info.name_for("TGT"), Ok("cysteine"));
}

#[test]
#[ignore]
fn test_cysteine_tgy() { // "compressed" name for TGT and TGC
let info = proteins::parse(make_pairs());
assert_eq!(info.name_for("TGT"), info.name_for("TGY"));
assert_eq!(info.name_for("TGC"), info.name_for("TGY"));
assert_eq!(info.name_for("UGU"), Ok("cysteine"));
}

#[test]
#[ignore]
fn test_stop() {
let info = proteins::parse(make_pairs());
assert_eq!(info.name_for("TAA"), Ok("stop codon"));
assert_eq!(info.name_for("UAA"), Ok("stop codon"));
}

#[test]
#[ignore]
fn test_valine() {
let info = proteins::parse(make_pairs());
assert_eq!(info.name_for("GTN"), Ok("valine"));
assert_eq!(info.name_for("GUU"), Ok("valine"));
}


#[test]
#[ignore]
fn test_isoleucine() {
let info = proteins::parse(make_pairs());
assert_eq!(info.name_for("ATH"), Ok("isoleucine"));
assert_eq!(info.name_for("AUU"), Ok("isoleucine"));
}

#[test]
#[ignore]
fn test_arginine_name() {
// In arginine CGA can be "compresed" both as CGN and as MGR
let info = proteins::parse(make_pairs());
assert_eq!(info.name_for("CGA"), Ok("arginine"));
assert_eq!(info.name_for("CGN"), Ok("arginine"));
assert_eq!(info.name_for("MGR"), Ok("arginine"));
assert_eq!(info.name_for("AGA"), Ok("arginine"));
assert_eq!(info.name_for("AGG"), Ok("arginine"));
}

#[test]
Expand All @@ -71,7 +61,7 @@ fn x_is_not_shorthand_so_is_invalid() {
#[ignore]
fn too_short_is_invalid() {
let info = proteins::parse(make_pairs());
assert!(info.name_for("AT").is_err());
assert!(info.name_for("AU").is_err());
}

#[test]
Expand All @@ -81,30 +71,60 @@ fn too_long_is_invalid() {
assert!(info.name_for("ATTA").is_err());
}

#[test]
#[ignore]
fn test_translates_rna_strand_into_correct_protein() {
let info = proteins::parse(make_pairs());
assert_eq!(info.of_rna("AUGUUUUGG").unwrap(),
vec!["methionine", "phenylalanine", "tryptophan"]);
}

#[test]
#[ignore]
fn test_stops_translation_if_stop_codon_present() {
let info = proteins::parse(make_pairs());
assert_eq!(info.of_rna("AUGUUUUAA").unwrap(),
vec!["methionine", "phenylalanine"]);
}

#[test]
#[ignore]
fn test_stops_translation_of_longer_strand() {
let info = proteins::parse(make_pairs());
assert_eq!(info.of_rna("UGGUGUUAUUAAUGGUUU").unwrap(),
vec!["tryptophan", "cysteine", "tyrosine"]);
}

#[test]
#[ignore]
fn test_invalid_codons() {
let info = proteins::parse(make_pairs());
assert!(info.of_rna("CARROT").is_err());
}

// The input data constructor. Returns a list of codon, name pairs.
fn make_pairs() -> Vec<(&'static str, &'static str)> {
let grouped = vec![
("isoleucine", vec!["ATT", "ATC", "ATA"]),
("leucine", vec!["CTT", "CTC", "CTA", "CTG", "TTA", "TTG"]),
("valine", vec!["GTT", "GTC", "GTA", "GTG"]),
("phenylalanine", vec!["TTT", "TTC"]),
("methionine", vec!["ATG"]),
("cysteine", vec!["TGT", "TGC"]),
("alanine", vec!["GCT", "GCC", "GCA", "GCG"]),
("glycine", vec!["GGT", "GGC", "GGA", "GGG"]),
("proline", vec!["CCT", "CCC", "CCA", "CCG"]),
("threonine", vec!["ACT", "ACC", "ACA", "ACG"]),
("serine", vec!["TCT", "TCC", "TCA", "TCG", "AGT", "AGC"]),
("tyrosine", vec!["TAT", "TAC"]),
("tryptophan", vec!["TGG"]),
("isoleucine", vec!["AUU", "AUC", "AUA"]),
("valine", vec!["GUU", "GUC", "GUA", "GUG"]),
("phenylalanine", vec!["UUU", "UUC"]),
("methionine", vec!["AUG"]),
("cysteine", vec!["UGU", "UGC"]),
("alanine", vec!["GCU", "GCC", "GCA", "GCG"]),
("glycine", vec!["GGU", "GGC", "GGA", "GGG"]),
("proline", vec!["CCU", "CCC", "CCA", "CCG"]),
("threonine", vec!["ACU", "ACC", "ACA", "ACG"]),
("serine", vec!["AGU", "AGC"]),
("tyrosine", vec!["UAU", "UAC"]),
("tryptophan", vec!["UGG"]),
("glutamine", vec!["CAA", "CAG"]),
("asparagine", vec!["AAT", "AAC"]),
("histidine", vec!["CAT", "CAC"]),
("asparagine", vec!["AAU", "AAC"]),
("histidine", vec!["CAU", "CAC"]),
("glutamic acid", vec!["GAA", "GAG"]),
("aspartic acid", vec!["GAT", "GAC"]),
("aspartic acid", vec!["GAU", "GAC"]),
("lysine", vec!["AAA", "AAG"]),
("arginine", vec!["CGT", "CGC", "CGA", "CGG", "AGA", "AGG"]),
("stop codon", vec!["TAA", "TAG", "TGA"])];
("arginine", vec!["CGU", "CGC", "CGA", "CGG", "AGA", "AGG"]),
("stop codon", vec!["UAA", "UAG", "UGA"])];
let mut pairs = Vec::<(&'static str, &'static str)>::new();
for (name, codons) in grouped.into_iter() {
for codon in codons {
Expand Down

0 comments on commit 772d684

Please sign in to comment.