RNA Transcription

1. Readme

RNA 转录

给定 DNA 链,返回其 RNA 补体(每个 RNA 转录).

DNA 和 RNA 链都是核苷酸序列.

DNA 中发现的四个核苷酸是腺嘌呤(A),胞嘧啶(C),鸟嘌呤(G)和胸腺嘧啶(T).

RNA 中发现的四个核苷酸是腺嘌呤(A),胞嘧啶(C),鸟嘌呤(G)和尿嘧啶(T).

给定 DNA 链,其转录的 RNA 链,通过用其互补物替换每个核苷酸而形成:

  • G- >C
  • C- >G
  • T- >A
  • A- >U

关于 Rust 实现的注释

通过在公共结构中使用私有字段,new函数会返回Option要么Result(在这里DNA::new&RNA::new),我们可以保证DNA内部的表达是正确的。因为每个有效的 DNA 字符串,都有一个有效的 RNA 字符串,所以我们不需要从to_rna返回一个Result/Option.

这解释了您将在测试中看到的类型签名。

资源

Hyperphysicshttp://hyperphysics.phy-astr.gsu.edu/hbase/Organic/transcription.html

2. 开始你的表演

#[derive(Debug, PartialEq)]
pub struct DNA;

#[derive(Debug, PartialEq)]
pub struct RNA;

impl DNA {
   pub fn new(dna: &str) -> Result<DNA, usize> {
       unimplemented!("Construct new DNA from '{}' string. If string contains invalid nucleotides return index of first invalid nucleotide", dna);
   }

   pub fn to_rna(self) -> RNA {
       unimplemented!("Transform DNA {:?} into corresponding RNA", self);
   }
}

impl RNA {
   pub fn new(rna: &str) -> Result<RNA, usize> {
       unimplemented!("Construct new RNA from '{}' string. If string contains invalid nucleotides return index of first invalid nucleotide", rna);
   }
}

3. 测试代码查看


# #![allow(unused_variables)]
#fn main() {
#[test]
fn test_valid_dna_input() {
   assert!(DNA::new("GCTA").is_ok());
}

#[test]
//#[ignore]
fn test_valid_rna_input() {
   assert!(RNA::new("CGAU").is_ok());
}

#[test]
//#[ignore]
fn test_invalid_dna_input() {
   // Invalid character
   assert_eq!(DNA::new("X").err(), Some(0));
   // Valid nucleotide, but invalid in context
   assert_eq!(DNA::new("U").err(), Some(0));
   // Longer string with contained errors
   assert_eq!(DNA::new("ACGTUXXCTTAA").err(), Some(4));
}

#[test]
//#[ignore]
fn test_invalid_rna_input() {
   // Invalid character
   assert!(RNA::new("X").is_err());
   // Valid nucleotide, but invalid in context
   assert!(RNA::new("T").is_err());
   // Longer string with contained errors
   assert!(RNA::new("ACGUTTXCUUAA").is_err());
}

#[test]
//#[ignore]
fn test_acid_equals_acid() {
   assert_eq!(DNA::new("CGA").unwrap(), DNA::new("CGA").unwrap());
   assert_ne!(DNA::new("CGA").unwrap(), DNA::new("AGC").unwrap());
   assert_eq!(RNA::new("CGA").unwrap(), RNA::new("CGA").unwrap());
   assert_ne!(RNA::new("CGA").unwrap(), RNA::new("AGC").unwrap());
}

#[test]
//#[ignore]
fn test_transcribes_cytosine_guanine() {
   assert_eq!(RNA::new("G").unwrap(), DNA::new("C").unwrap().to_rna());
}

#[test]
//#[ignore]
fn test_transcribes_guanine_cytosine() {
   assert_eq!(RNA::new("C").unwrap(), DNA::new("G").unwrap().to_rna());
}

#[test]
//#[ignore]
fn test_transcribes_adenine_uracil() {
   assert_eq!(RNA::new("U").unwrap(), DNA::new("A").unwrap().to_rna());
}

#[test]
//#[ignore]
fn test_transcribes_thymine_to_adenine() {
   assert_eq!(RNA::new("A").unwrap(), DNA::new("T").unwrap().to_rna());
}

#[test]
//#[ignore]
fn test_transcribes_all_dna_to_rna() {
   assert_eq!(
       RNA::new("UGCACCAGAAUU").unwrap(),
       DNA::new("ACGTGGTCTTAA").unwrap().to_rna()
   )
}

#}

4. 答案


# #![allow(unused_variables)]
#fn main() {
/// The possible nucleotides in DNA and RNA
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum Nucleotide {
   Adenine,
   Cytosine,
   Guanine,
   Thymine,
   Uracil,
}

impl Nucleotide {
   /// Parses a nucleotide from its character value, if valid.
   fn from_char(ch: char) -> Option<Nucleotide> {
       Some(match ch {
           'A' => Nucleotide::Adenine,
           'C' => Nucleotide::Cytosine,
           'G' => Nucleotide::Guanine,
           'T' => Nucleotide::Thymine,
           'U' => Nucleotide::Uracil,
           _ => {
               return None;
           }
       })
   }
}

/// A vector of nucleotides
///
/// Guaranteed that Uracil is not present thanks to `new`.
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct DNA(Vec<Nucleotide>);

impl DNA {
   /// Parse a DNA string, checking it is valid.
   ///
   /// The error value is the first invalid character index (char index, not utf8).
   pub fn new(input: &str) -> Result<DNA, usize> {
       let mut out = Vec::new();
       for (idx, ch) in input.chars().enumerate() {
           match Nucleotide::from_char(ch) {
               Some(Nucleotide::Uracil) | None => {
                   return Err(idx);
               }
               Some(n) => {
                   out.push(n);
               }
           }
       }
       Ok(DNA(out))
   }

   pub fn to_rna(mut self) -> RNA {
       for nuc in self.0.iter_mut() {
           *nuc = match *nuc {
               Nucleotide::Adenine => Nucleotide::Uracil,
               Nucleotide::Cytosine => Nucleotide::Guanine,
               Nucleotide::Guanine => Nucleotide::Cytosine,
               Nucleotide::Thymine => Nucleotide::Adenine,
               Nucleotide::Uracil => unreachable!(),
           }
       }
       RNA(self.0)
   }
}

#[derive(Debug, Eq, PartialEq, Clone)]
pub struct RNA(Vec<Nucleotide>);

impl RNA {
   /// Parse a RNA string, checking it is valid.
   ///
   /// The error value is the first invalid character index (char index, not utf8).
   pub fn new(input: &str) -> Result<RNA, usize> {
       let mut out = Vec::new();
       for (idx, ch) in input.chars().enumerate() {
           match Nucleotide::from_char(ch) {
               Some(Nucleotide::Thymine) | None => {
                   return Err(idx);
               }
               Some(n) => {
                   out.push(n);
               }
           }
       }
       Ok(RNA(out))
   }
}

#}



填充/相关