From 8f8f35f06feb293a6158454935d492e22e4649d6 Mon Sep 17 00:00:00 2001 From: Fizzizist Date: Sun, 23 Feb 2025 12:26:51 -0500 Subject: [PATCH] solved REVP finally --- rust/src/solutions/revp.rs | 59 ++++++++++++++++++++++++++++++-- rust/src/utils.rs | 70 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+), 2 deletions(-) diff --git a/rust/src/solutions/revp.rs b/rust/src/solutions/revp.rs index 0db09a0..57d24be 100644 --- a/rust/src/solutions/revp.rs +++ b/rust/src/solutions/revp.rs @@ -1,3 +1,58 @@ -pub fn revp(file_content: String) -> String { - "placeholder".to_string() +use crate::utils::{get_dna_complement, read_fasta}; + +fn get_revps(dna: &str, complement: &str) -> Vec { + let mut out_vec: Vec = Vec::new(); + for i in 4..dna.len() + 1 { + let sub_rev_comp: &String = &complement[..i].chars().rev().collect(); + if sub_rev_comp == &dna[..i] { + out_vec.push(sub_rev_comp.len()) + } + } + out_vec +} + +pub fn revp(file_content: String) -> String { + let fastas = read_fasta(&file_content); + let fasta = &fastas[0]; + let complement = get_dna_complement(&fasta.sequence); + let mut out_vec: Vec = Vec::new(); + let dna_len = fasta.sequence.len(); + + for position in 1..dna_len - 2 { + let mut last_pos = position + 11; + if last_pos > dna_len { + last_pos = dna_len; + } + let revps = get_revps( + &fasta.sequence[position - 1..last_pos], + &complement[position - 1..last_pos], + ); + for r in revps.iter() { + out_vec.push(format!("{} {}", position, r)); + } + } + + return out_vec.join("\n"); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_revp() { + let input_content = r#">Rosalind_24 +TCAATGCATGCGGGTCTATATGCAT"# + .to_string(); + let expected = r#"4 6 +5 4 +6 6 +7 4 +17 4 +18 4 +20 6 +21 4"# + .to_string(); + assert_eq!(revp(input_content), expected); + } } diff --git a/rust/src/utils.rs b/rust/src/utils.rs index c45d7d1..65f14f0 100644 --- a/rust/src/utils.rs +++ b/rust/src/utils.rs @@ -1,6 +1,11 @@ use crate::{solutions, Problem}; use std::{fs, io}; +pub struct FastaRecord { + pub id: String, + pub sequence: String, +} + pub fn run_solution(problem: Problem, in_file: &String, out_file: &String) { // parse the input file into a string let solution: io::Result = match fs::read_to_string(in_file) { @@ -18,3 +23,68 @@ pub fn run_solution(problem: Problem, in_file: &String, out_file: &String) { Err(e) => println!("An error occured reading the input file: {e}"), }; } + +pub fn read_fasta(file_content: &String) -> Vec { + let mut records: Vec = Vec::new(); + let mut id = String::new(); + let mut sequence = String::new(); + + for line in file_content.lines() { + if line.starts_with('>') { + if !id.is_empty() { + records.push(FastaRecord { + id: id.clone(), + sequence: sequence.clone(), + }); + id.clear(); + sequence.clear(); + } + id = line[1..].to_string(); + } else { + sequence.push_str(line); + } + } + records.push(FastaRecord { + id: id.clone(), + sequence: sequence.clone(), + }); + records +} + +pub fn get_dna_complement(dna: &String) -> String { + let mut complement = String::new(); + for base in dna.chars() { + match base { + 'A' => complement.push('T'), + 'T' => complement.push('A'), + 'C' => complement.push('G'), + 'G' => complement.push('C'), + _ => panic!("Invalid DNA base"), + } + } + complement +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_read_fasta() { + let file_content = + ">Rosalind_1\nGATTACA\nGTACACACACATTTTTGG\n>Rosalind_2\nTACG\n".to_string(); + let records = read_fasta(&file_content); + assert_eq!(records.len(), 2); + assert_eq!(records[0].id, "Rosalind_1"); + assert_eq!(records[0].sequence, "GATTACAGTACACACACATTTTTGG"); + assert_eq!(records[1].id, "Rosalind_2"); + assert_eq!(records[1].sequence, "TACG"); + } + + #[test] + fn test_get_dna_complement() { + let dna = "GATTACA".to_string(); + let expected = "CTAATGT".to_string(); + assert_eq!(get_dna_complement(&dna), expected); + } +}