Решение на Думи на Фибоначи от Николета Михайлова
Към профила на Николета Михайлова
Резултати
- 17 точки от тестове
- 0 бонус точки
- 17 точки общо
- 17 успешни тест(а)
- 3 неуспешни тест(а)
Код
//kind of messy but hey, strings in rust are something else...
pub struct FibIter {
fib1: u32,
fib2: u32,
counter: u32,
}
impl FibIter {
pub fn new() -> FibIter {
FibIter {fib1: 1, fib2: 1, counter: 0}
}
pub fn next(&mut self) -> u32 {
self.counter+=1;
if self.counter <= 2 { // since it gets incremented beforehand
self.fib1
}
else {
let temp: u32 = self.fib1;
self.fib1 = self.fib2;
self.fib2 = temp + self.fib1;
self.fib2
}
}
pub fn rev(self) -> RevFibIter {
RevFibIter {fib1: self.fib1, fib2: self.fib2, counter: 0}
}
}
pub struct RevFibIter {
fib1: u32, // fib1 is lower in value
fib2: u32,
counter: u32,
}
impl RevFibIter {
// that's a really counterintuitive name for the function :D
pub fn next(&mut self) -> Option<u32> {
self.counter+=1;
if self.fib1 < 1 { return None; }
//maybe not the best approach, but it works
if self.counter == 1 { return Some(self.fib2); }
let temp = self.fib1;
self.fib1 = self.fib2 - self.fib1;
self.fib2 = temp;
Some(self.fib2)
}
}
pub fn fib_split(text: &str) -> Vec<String> {
let mut fib_iter: FibIter = FibIter::new();
let chars: Vec<char> = text.chars().collect();
let mut words: Vec<String> = Vec::new();
let mut fib_n: usize = fib_iter.next() as usize;
let mut begin: usize = 0;
while fib_n <= chars.len() {
//idk if there was an easier way using slices :D
let mut word: String = String::new();
for i in begin..fib_n+begin {
if i >= chars.len() { break; }
word.push(chars[i]);
}
begin += fib_n;
fib_n = fib_iter.next() as usize;
if !word.is_empty() { words.push(word); }
}
words
}
pub fn fib_split_n(text: &str, n: u32) -> (Vec<String>, &str) {
let n: usize = n as usize;
let mut words: Vec<String> = fib_split(text);
if words.len() < n {
panic!("String is too short");
}
words.truncate(n);
let mut length: usize = 0;
for word in &words {
//adds the number of bytes in the word, so it's ok:)
length += word.len();
}
(words, &text[length..])
}
/*
what separates it from the previous two is that it
returns an iterator and it is guaranteed that the iterator
won't go past the actual needed values (unlike the previous two).
that's because fib_split splits the ENTIRE string and
fib_split_n only returns the first n elements of the resulting vector
*/
pub fn fib_split_n_iter(text: &str, n: u32) -> ((Vec<String>, FibIter), &str) {
let mut n: usize = n as usize;
let mut fib_iter: FibIter = FibIter::new();
let chars: Vec<char> = text.chars().collect();
let mut words: Vec<String> = Vec::new();
let mut fib_n: usize = fib_iter.next() as usize;
let mut begin: usize = 0;
let mut length = 0;
while fib_n <= chars.len() && n > 0 {
let mut word: String = String::new();
for i in begin..fib_n+begin {
if i >= chars.len() { break; }
word.push(chars[i]);
//takes the size of the character in utf8
//and adds it to the length
//so that i can properly slice the string later:)
length+=chars[i].len_utf8();
}
begin += fib_n;
fib_n = fib_iter.next() as usize;
if !word.is_empty() { words.push(word); }
n-=1;
}
((words, fib_iter), &text[length..])
}
pub fn fib_split_rev(text: &str, n: u32, fib_iter: FibIter) -> (Vec<String>, &str) {
if n == 0 { return (Vec::new(), text); }
let mut fib_iter_rev: RevFibIter = fib_iter.rev();
fib_iter_rev.next();
let chars: Vec<char> = text.chars().collect();
let mut words: Vec<String> = Vec::new();
let mut fib_n: Option<usize> = fib_iter_rev.next().map(|n| n as usize);
let mut begin: usize = 0;
let mut length = 0;
while fib_n.is_some() {
let mut word: String = String::new();
for i in begin..fib_n.unwrap()+begin {
if i >= chars.len() { break; }
word.push(chars[i]);
length+=chars[i].len_utf8();
}
begin += fib_n.unwrap();
fib_n = fib_iter_rev.next().map(|n| n as usize);
if !word.is_empty() { words.push(word); }
}
(words, &text[length..])
}
pub fn fib_split_n_symmetric(text: &str, n: u32) -> (Vec<String>, &str) {
let ((mut first_words, iter), rest): ((Vec<String>, FibIter), &str) = fib_split_n_iter(text, n);
let (mut second_words, rest2) = fib_split_rev(rest, n, iter);
first_words.append(&mut second_words);
//assuming i understood the problem description correctly
if first_words.len() != 2*n as usize {
panic!("string cannot be split symmetrically")
}
(first_words, &rest2)
}
Лог от изпълнението
Compiling solution v0.1.0 (/tmp/d20241104-1739405-igdyy2/solution) Finished test [unoptimized + debuginfo] target(s) in 0.94s 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_cyrillic ... ok test solution_test::fib_split_empty ... ok test solution_test::fib_split_n_ascii ... ok test solution_test::fib_split_n_ascii_exact ... ok test solution_test::fib_split_n_ascii_panic ... FAILED test solution_test::fib_split_n_cyrillic ... ok 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_exact ... ok test solution_test::fib_split_n_symmetric_cyrillic ... ok test solution_test::fib_split_n_symmetric_zero ... ok test solution_test::fib_split_n_symmetric_cyrillic_panic ... ok test solution_test::fib_split_n_zero ... ok test solution_test::rev_fib_iter ... ok test solution_test::rev_fib_iter_empty ... FAILED failures: ---- solution_test::fib_split_n_ascii_panic stdout ---- thread 'solution_test::fib_split_n_ascii_panic' panicked at 'String is too short', src/lib.rs:81: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 ---- solution_test::rev_fib_iter_empty stdout ---- thread 'solution_test::rev_fib_iter_empty' panicked at 'assertion failed: `(left == right)` left: `Some(1)`, right: `None`', tests/solution_test.rs:43:5 failures: solution_test::fib_split_n_ascii_panic solution_test::fib_split_n_cyrillic_panic solution_test::rev_fib_iter_empty test result: FAILED. 17 passed; 3 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s error: test failed, to rerun pass `--test solution_test`