Решение на Сметки с ДНК от Ивайло Димитров

Обратно към всички решения

Към профила на Ивайло Димитров

Резултати

  • 20 точки от тестове
  • 1 бонус точка
  • 21 точки общо
  • 12 успешни тест(а)
  • 0 неуспешни тест(а)

Код

use core::panic;
pub struct NucleotideCounter {
pub a: usize,
pub c: usize,
pub g: usize,
pub t: usize,
}
pub fn counts(dna: &[char]) -> NucleotideCounter {
let mut nc = NucleotideCounter { a: 0, c: 0, g: 0, t: 0 };
for ch in dna
{
match *ch {
'A' => nc.a += 1,
'C' => nc.c += 1,
'G' => nc.g += 1,
'T' => nc.t += 1,
_ => panic!("не може така")
}
}
nc
}
pub fn dna_complement(dna: &[char]) -> Vec<char> {
let mut complement: Vec<char> = Vec::new();
for ch in dna
{
match *ch {
'A' => complement.push('T'),
'C' => complement.push('G'),
'G' => complement.push('C'),
'T' => complement.push('A'),
_ => panic!("няма да може")
}
}
complement
}
pub fn reverse_rna_complement(dna: &[char]) -> Vec<char> {
let mut complement: Vec<char> = Vec::new();
for ch in dna.iter().rev()
{
match *ch {
'A' => complement.push('U'),
'C' => complement.push('G'),
'G' => complement.push('C'),
'T' => complement.push('A'),
_ => panic!("няма да стане")
}
}
complement
}
#[cfg(test)]
mod tests {
use crate::*;
fn compare_counters(c1: &NucleotideCounter, c2: &NucleotideCounter) -> bool
{
c1.a == c2.a && c1.c == c2.c && c1.g == c2.g && c1.t == c2.t
}
#[test]
fn count_test() {
let valid_input1: Vec<char> = "".chars().collect();
let valid_input2: Vec<char> = "GC".chars().collect();
let valid_input3: Vec<char> = "AT".chars().collect();
let valid_input4: Vec<char> = "AAAAAA".chars().collect();
let valid_input5: Vec<char> = "GCCCGT".chars().collect();
let valid_input6: Vec<char> = "ACTGGTCA".chars().collect();
let expected1 = NucleotideCounter{a: 0, c: 0, g: 0, t: 0};
let expected2 = NucleotideCounter{a: 0, c: 1, g: 1, t: 0};
let expected3 = NucleotideCounter{a: 1, c: 0, g: 0, t: 1};
let expected4 = NucleotideCounter{a: 6, c: 0, g: 0, t: 0};
let expected5 = NucleotideCounter{a: 0, c: 3, g: 2, t: 1};
let expected6 = NucleotideCounter{a: 2, c: 2, g: 2, t: 2};
let counter1 = counts(&valid_input1);
let counter2 = counts(&valid_input2);
let counter3 = counts(&valid_input3);
let counter4 = counts(&valid_input4);
let counter5 = counts(&valid_input5);
let counter6 = counts(&valid_input6);
assert!(compare_counters(&counter1, &expected1));
assert!(compare_counters(&counter2, &expected2));
assert!(compare_counters(&counter3, &expected3));
assert!(compare_counters(&counter4, &expected4));
assert!(compare_counters(&counter5, &expected5));
assert!(compare_counters(&counter6, &expected6));
}

Обилен комплект от assertion-и 👍. За четимост, бих посъветвал counter и expected стойностите да са по-близо една до друга. Т.е. вместо да ги групираш на входове и изходи, да групираш един вход с един изход -- така по-лесно може визуално да се види кое с какво е свързано. Същото се отнася и за някои от долните тестове.

#[test]
#[should_panic]
fn count_panic_test1()
{
let invalid_input: Vec<char> = "x".chars().collect();
counts(&invalid_input);
}
#[test]
#[should_panic]
fn count_panic_test2()
{
let invalid_input: Vec<char> = "ACX".chars().collect();
counts(&invalid_input);
}
#[test]
#[should_panic]
fn count_panic_test3()
{
let invalid_input: Vec<char> = ";TG".chars().collect();
counts(&invalid_input);
}
#[test]
#[should_panic]
fn count_panic_test4()
{
let invalid_input: Vec<char> = "G,C".chars().collect();
counts(&invalid_input);
}
#[test]
fn dna_complement_test()
{
let valid_input1: Vec<char> = "".chars().collect();
let valid_input2: Vec<char> = "GC".chars().collect();
let valid_input3: Vec<char> = "AT".chars().collect();
let valid_input4: Vec<char> = "AAAAAA".chars().collect();
let valid_input5: Vec<char> = "GCCCGT".chars().collect();
let valid_input6: Vec<char> = "ACTGGTCA".chars().collect();
let expected1: Vec<char> = "".chars().collect();
let expected2: Vec<char> = "CG".chars().collect();
let expected3: Vec<char> = "TA".chars().collect();
let expected4: Vec<char> = "TTTTTT".chars().collect();
let expected5: Vec<char> = "CGGGCA".chars().collect();
let expected6: Vec<char> = "TGACCAGT".chars().collect();
assert_eq!(dna_complement(&valid_input1), expected1);
assert_eq!(dna_complement(&valid_input2), expected2);
assert_eq!(dna_complement(&valid_input3), expected3);
assert_eq!(dna_complement(&valid_input4), expected4);
assert_eq!(dna_complement(&valid_input5), expected5);
assert_eq!(dna_complement(&valid_input6), expected6);
}
#[test]
#[should_panic]
fn dna_complement_panic_test1()
{
let invalid_input: Vec<char> = "x".chars().collect();
dna_complement(&invalid_input);
}
#[test]
#[should_panic]
fn dna_complement_panic_test2()
{
let invalid_input: Vec<char> = "ACX".chars().collect();
dna_complement(&invalid_input);
}
#[test]
#[should_panic]
fn dna_complement_panic_test3()
{
let invalid_input: Vec<char> = ";TG".chars().collect();
dna_complement(&invalid_input);
}
#[test]
#[should_panic]
fn dna_complement_panic_test4()
{
let invalid_input: Vec<char> = "G,C".chars().collect();
dna_complement(&invalid_input);
}
#[test]
fn reverse_rna_complement_test()
{
let valid_input1: Vec<char> = "".chars().collect();
let valid_input2: Vec<char> = "GC".chars().collect();
let valid_input3: Vec<char> = "AT".chars().collect();
let valid_input4: Vec<char> = "AAAAAA".chars().collect();
let valid_input5: Vec<char> = "GCCCGT".chars().collect();
let valid_input6: Vec<char> = "ACTGGTCA".chars().collect();
let expected1: Vec<char> = "".chars().collect();
let expected2: Vec<char> = "GC".chars().collect();
let expected3: Vec<char> = "AU".chars().collect();
let expected4: Vec<char> = "UUUUUU".chars().collect();
let expected5: Vec<char> = "ACGGGC".chars().collect();
let expected6: Vec<char> = "UGACCAGU".chars().collect();
assert_eq!(reverse_rna_complement(&valid_input1), expected1);
assert_eq!(reverse_rna_complement(&valid_input2), expected2);
assert_eq!(reverse_rna_complement(&valid_input3), expected3);
assert_eq!(reverse_rna_complement(&valid_input4), expected4);
assert_eq!(reverse_rna_complement(&valid_input5), expected5);
assert_eq!(reverse_rna_complement(&valid_input6), expected6);
}
#[test]
#[should_panic]
fn reverse_rna_complement_panic_test1()
{
let invalid_input: Vec<char> = "x".chars().collect();
reverse_rna_complement(&invalid_input);
}
#[test]
#[should_panic]
fn reverse_rna_complement_panic_test2()
{
let invalid_input: Vec<char> = "ACX".chars().collect();
reverse_rna_complement(&invalid_input);
}
#[test]
#[should_panic]
fn reverse_rna_complement_panic_test3()
{
let invalid_input: Vec<char> = ";TG".chars().collect();
reverse_rna_complement(&invalid_input);
}
#[test]
#[should_panic]
fn reverse_rna_complement_panic_test4()
{
let invalid_input: Vec<char> = "G,C".chars().collect();
reverse_rna_complement(&invalid_input);
}
}

Лог от изпълнението

Compiling solution v0.1.0 (/tmp/d20220112-2706256-sxrjf1/solution)
    Finished test [unoptimized + debuginfo] target(s) in 5.67s
     Running tests/solution_test.rs (target/debug/deps/solution_test-4c880d3f0adaac34)

running 12 tests
test solution_test::test_counts_basic ... ok
test solution_test::test_counts_big ... ok
test solution_test::test_counts_panic1 - should panic ... ok
test solution_test::test_counts_panic2 - should panic ... ok
test solution_test::test_counts_zero ... ok
test solution_test::test_dna_complement_big ... ok
test solution_test::test_dna_complement_empty ... ok
test solution_test::test_dna_complement_panic - should panic ... ok
test solution_test::test_reverse_rna_complement_big ... ok
test solution_test::test_reverse_rna_complement_empty ... ok
test solution_test::test_reverse_rna_complement_panic1 - should panic ... ok
test solution_test::test_reverse_rna_complement_panic2 - should panic ... ok

test result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

История (1 версия и 4 коментара)

Ивайло качи първо решение на 25.10.2021 02:08 (преди почти 4 години)

Давам ти бонус точка за тестовете -- сетил си се да отделиш паниращите едни от други, и си покрил и трите функции. Може би проверките са повече, отколкото си заслужава -- да тестваш complement-а на "ACTGGTCA" вероятно е достатъчно, за да нямаш нужда от, примерно "GCCCGT". От друга страна, да провериш че функцията работи очаквано с празен низ е важно и е различна проверка от другите. Все пак, по-добре повече от нужните, отколкото по-малко от нужните :)