Решение на Думи на Фибоначи от Ивайло Генчев
Резултати
- 18 точки от тестове
- 0 бонус точки
- 18 точки общо
- 18 успешни тест(а)
- 2 неуспешни тест(а)
Код
pub struct FibIter {
curr_num: u32,
next_num: u32,
}
pub struct RevFibIter {
prev_num: u32,
curr_num: u32,
}
impl FibIter {
pub fn new() -> FibIter {
FibIter {
curr_num: 0,
next_num: 1,
}
}
pub fn next(&mut self) -> u32 {
self.next_num = self.next_num + self.curr_num;
self.curr_num = self.next_num - self.curr_num;
self.curr_num
}
pub fn rev(self) -> RevFibIter {
RevFibIter {
curr_num: self.next_num,
prev_num: self.curr_num,
}
}
}
impl RevFibIter {
pub fn next(&mut self) -> Option<u32> {
if self.prev_num == 0 {
return None;
}
self.prev_num = self.curr_num - self.prev_num;
self.curr_num = self.curr_num - self.prev_num;
Some(self.curr_num)
}
}
pub fn fib_split(text: &str) -> Vec<String> {
let mut fib_vec: Vec<String> = Vec::new();
let mut fib_iter = FibIter::new();
let mut text_iter = text.chars();
let mut text_end: bool = false;
loop {
let fib_num = fib_iter.next();
let mut fib_substr = String::with_capacity(fib_num as usize);
for _ in 0..fib_num {
match text_iter.next() {
Some(ch) => {
fib_substr.push(ch);
}
None => {
text_end = true;
break;
}
}
}
// fib_substr is empty only when the text's length is a Fibonacci
// number and we're at its end
if !fib_substr.is_empty() {
fib_vec.push(fib_substr);
}
if text_end {
break fib_vec;
}
}
}
pub fn fib_split_n(text: &str, n: u32) -> (Vec<String>, &str) {
let mut fib_words_vec = fib_split(text);
if n as usize > fib_words_vec.len() {
panic!("Text cannot be split into {n} parts!")
}
fib_words_vec.truncate(n as usize);
let fib_words_letters = fib_words_vec
.iter()
.fold(0, |bytes, word| bytes + word.bytes().count());
(fib_words_vec, text.split_at(fib_words_letters).1)
}
pub fn fib_split_n_symmetric(text: &str, n: u32) -> (Vec<String>, &str) {
if n == 0 {
return (Vec::new(), text);
}
let (mut fib_split, remaining_text) = fib_split_n(text, n);
let mut text_iter = remaining_text.chars();
let mut fib_iter = FibIter::new();
for _ in 0..n {
fib_iter.next();
}
let mut rev_fib_iter = fib_iter.rev();
while let Some(fib_num) = rev_fib_iter.next() {
let mut fib_substr = String::with_capacity(fib_num as usize);
for _ in 0..fib_num {
match text_iter.next() {
Some(ch) => fib_substr.push(ch),
None => {
panic!("Text is too small! Cannot split into {n} symmetric words.")
}
}
}
fib_split.push(fib_substr);
}
let fib_words_letters = fib_split
.iter()
.fold(0, |bytes, word| bytes + word.bytes().count());
(fib_split, text.split_at(fib_words_letters).1)
// (fib_split, text_iter.collect()) // if we want to return String
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_basic() {
let mut fib_iter = FibIter::new();
fib_iter.next();
let mut rev_fib_iter: RevFibIter = fib_iter.rev();
rev_fib_iter.next();
let words: Vec<String> = fib_split("Fibonacci words!");
assert_eq!(words, &["F", "i", "bo", "nac", "ci wo", "rds!"]);
let (words, rest) = fib_split_n("Lorem ipsum dolor sit amet.", 6);
assert_eq!(words, &["L", "o", "re", "m i", "psum ", "dolor si"]);
assert_eq!(rest, "t amet.");
let (words, rest) = fib_split_n_symmetric("Lorem ipsum dolor sit amet.", 5);
assert_eq!(
words,
&["L", "o", "re", "m i", "psum ", "dolor", " si", "t ", "a", "m"]
);
assert_eq!(rest, "et.");
}
#[test]
fn test_fib_iter_next() {
let mut fib_iter = FibIter::new();
assert_eq!(fib_iter.next(), 1);
assert_eq!(fib_iter.next(), 1);
assert_eq!(fib_iter.next(), 2);
assert_eq!(fib_iter.next(), 3);
assert_eq!(fib_iter.next(), 5);
assert_eq!(fib_iter.next(), 8);
}
#[test]
fn test_fib_split_without_truncated_end() {
let text: &str = "Здравей";
assert_eq!(fib_split(text), vec!["З", "д", "ра", "вей"])
}
#[test]
fn test_fib_split_with_truncated_end() {
let text: &str = "Здравей, Свят!";
assert_eq!(fib_split(text), vec!["З", "д", "ра", "вей", ", Свя", "т!"])
}
#[test]
fn test_fib_split_one_letter() {
let text: &str = "З";
assert_eq!(fib_split(text), vec!["З"])
}
#[test]
fn test_fib_split_empty_string() {
let text: &str = "";
let res: Vec<String> = Vec::new();
assert_eq!(fib_split(text), res)
}
#[test]
fn test_fib_split_mixed_char_size() {
let text: &str = "Zдrаvеj";
assert_eq!(fib_split(text), vec!["Z", "д", "rа", "vеj"])
}
#[test]
fn test_fib_split_n() {
let text: &str = "Здравей";
assert_eq!(
fib_split_n(text, 3),
(
vec![String::from("З"), String::from("д"), String::from("ра")],
"вей"
)
)
}
#[test]
fn test_fib_split_n_with_empty_vec() {
let text: &str = "Здравей";
assert_eq!(fib_split_n(text, 0), (vec![], "Здравей"))
}
#[test]
fn test_fib_split_n_with_whole_text_in_vec() {
let text: &str = "Здравей";
assert_eq!(
fib_split_n(text, 4),
(
vec![
String::from("З"),
String::from("д"),
String::from("ра"),
String::from("вей")
],
""
)
)
}
#[test]
#[should_panic]
fn test_invalid_fib_split_n_with_too_large_n() {
let text: &str = "Здравей";
fib_split_n(text, 5);
}
#[test]
fn test_rev_fib_iter_next() {
let mut fib_iter = FibIter::new();
fib_iter.next(); // 1
fib_iter.next(); // 1
fib_iter.next(); // 2
fib_iter.next(); // 3
fib_iter.next(); // 5
fib_iter.next(); // 8
let mut rev_fib_iter = fib_iter.rev();
assert_eq!(rev_fib_iter.next(), Some(8));
assert_eq!(rev_fib_iter.next(), Some(5));
assert_eq!(rev_fib_iter.next(), Some(3));
assert_eq!(rev_fib_iter.next(), Some(2));
assert_eq!(rev_fib_iter.next(), Some(1));
assert_eq!(rev_fib_iter.next(), Some(1));
assert_eq!(rev_fib_iter.next(), None);
assert_eq!(rev_fib_iter.next(), None);
}
#[test]
fn test_rev_fib_iter_with_one_prev_next() {
let mut fib_iter = FibIter::new();
fib_iter.next();
let mut rev_fib_iter = fib_iter.rev();
assert_eq!(rev_fib_iter.next(), Some(1));
}
#[test]
fn test_rev_fib_iter_without_prev_next() {
let mut rev_fib_iter = FibIter::new().rev();
assert_eq!(rev_fib_iter.next(), None);
}
#[test]
fn test_fib_split_n_symmetric_without_text() {
let (words, rest) = fib_split_n_symmetric("Здравей, свят!", 4);
assert_eq!(words, &["З", "д", "ра", "вей", ", с", "вя", "т", "!"]);
assert_eq!(rest, "");
}
#[test]
#[should_panic]
fn test_fib_split_n_symmetric_with_empty_input() {
fib_split_n_symmetric("", 1);
}
#[test]
#[should_panic]
fn test_invalid_fib_split_n_symmetric_too_much_words() {
fib_split_n_symmetric("Здравей, свят!", 5);
}
#[test]
fn test_fib_split_n_symmetric_1_word_smallest_input() {
let (words, rest) = fib_split_n_symmetric("Зд", 1);
assert_eq!(words, &["З", "д"]);
assert_eq!(rest, "");
}
}
Лог от изпълнението
Compiling solution v0.1.0 (/tmp/d20241104-1739405-1f6w854/solution) Finished test [unoptimized + debuginfo] target(s) in 0.90s Running tests/solution_test.rs (target/debug/deps/solution_test-1428e1090729d165) running 20 tests test solution_test::fib_iter ... ok test solution_test::fib_split_ascii ... ok test solution_test::fib_split_empty ... ok test solution_test::fib_split_cyrillic ... ok test solution_test::fib_split_n_ascii ... ok test solution_test::fib_split_n_ascii_exact ... ok test solution_test::fib_split_n_cyrillic ... ok test solution_test::fib_split_n_ascii_panic ... FAILED test solution_test::fib_split_n_cyrillic_exact ... ok test solution_test::fib_split_n_cyrillic_panic ... FAILED test solution_test::fib_split_n_symmetric_ascii ... ok test solution_test::fib_split_n_symmetric_ascii_exact ... ok test solution_test::fib_split_n_symmetric_ascii_panic ... ok test solution_test::fib_split_n_symmetric_cyrillic ... ok test solution_test::fib_split_n_symmetric_cyrillic_exact ... ok test solution_test::fib_split_n_symmetric_cyrillic_panic ... ok test solution_test::fib_split_n_symmetric_zero ... ok test solution_test::rev_fib_iter ... ok test solution_test::fib_split_n_zero ... ok test solution_test::rev_fib_iter_empty ... ok failures: ---- solution_test::fib_split_n_ascii_panic stdout ---- thread 'solution_test::fib_split_n_ascii_panic' panicked at 'Text cannot be split into 1 parts!', src/lib.rs:87:9 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace thread 'solution_test::fib_split_n_ascii_panic' panicked at 'assertion failed: catch_unwind(|| fib_split_n(\"abcd_123\", 5)).is_err()', tests/solution_test.rs:96:5 ---- solution_test::fib_split_n_cyrillic_panic stdout ---- thread 'solution_test::fib_split_n_cyrillic_panic' panicked at 'assertion failed: catch_unwind(|| fib_split_n(\"манджа_with_грозде\", 6)).is_err()', tests/solution_test.rs:119:5 failures: solution_test::fib_split_n_ascii_panic solution_test::fib_split_n_cyrillic_panic test result: FAILED. 18 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s error: test failed, to rerun pass `--test solution_test`