rosalind-solutions/rust/src/utils.rs
2025-03-15 16:07:47 -04:00

129 lines
3.4 KiB
Rust

use crate::solutions;
use std::{fs, io};
pub const AMINO_ACID_MASS_TABLE: [(char, f64); 20] = [
('A', 71.03711),
('C', 103.00919),
('D', 115.02694),
('E', 129.04259),
('F', 147.06841),
('G', 57.02146),
('H', 137.05891),
('I', 113.08406),
('K', 128.09496),
('L', 113.08406),
('M', 131.04049),
('N', 114.04293),
('P', 97.05276),
('Q', 128.05858),
('R', 156.10111),
('S', 87.03203),
('T', 101.04768),
('V', 99.06841),
('W', 186.07931),
('Y', 163.06333),
];
pub struct FastaRecord {
pub id: String,
pub sequence: String,
}
#[derive(clap::ValueEnum, Clone, Debug)]
pub enum Problem {
REVP,
PRTM,
IEV,
LIA,
BINS,
MAJ,
}
pub fn run_solution(problem: Problem, in_file: &String, out_file: &String) {
// parse the input file into a string
let solution: io::Result<String> = match fs::read_to_string(in_file) {
Ok(content) => match problem {
Problem::REVP => Ok(solutions::revp(content)),
Problem::PRTM => Ok(solutions::prtm(content)),
Problem::IEV => Ok(solutions::iev(content)),
Problem::LIA => Ok(solutions::lia(content)),
Problem::BINS => Ok(solutions::bins(content)),
Problem::MAJ => Ok(solutions::maj(content)),
},
Err(e) => Err(e),
};
match solution {
Ok(out_content) => match fs::write(out_file, &out_content) {
Ok(_) => println!("{:?}", out_content),
Err(e) => println!("Error writing to output file: {e}"),
},
Err(e) => println!("An error occured reading the input file: {e}"),
};
}
pub fn read_fasta(file_content: &String) -> Vec<FastaRecord> {
let mut records: Vec<FastaRecord> = 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);
}
}