Word Changer

Краен срок
16.01.2020 17:00

Срокът за предаване на решения е отминал

Word Changer

Ако искаме да поправяме правопис със spell checker-а от домашно 3, ще ни трябва нещо, което да цикли по думите на някакъв текст и да ги замества с вероятните fix-ове. Това е може би малко смело, предвид че може spell checker-а да греши, но все пак ще пробваме да имплементираме нещо такова.

Първо, искаме да итерираме по думи:

/// Забележете, че полето `source` не е публично, но сме го сложили, за да се компилира празния код
/// -- итератора е свързан по lifetime с низа, с който се вика.
///
/// Свободни сте да добавите още полета, ако ви трябват (вероятно ще ви трябват).
///
pub struct WordIterator<'a> {
    source: &'a str,
    // ...
}

impl<'a> WordIterator<'a> {
    pub fn new(source: &'a str) -> Self {
        unimplemented!()
    }
}

/// Този тип описва какъв вид текст връща итератора. Детайли по-долу.
///
#[derive(Debug, PartialEq)]
pub enum SegmentType {
    Word,
    NonWord,
}

/// Итератора ще връща двойка низ и типа на този низ -- дали е дума или не-дума. Целта е да
/// итерираме по целия низ, на части.
///
/// Символ, който е част от "дума" e всеки, за което `char::is_alphabetic` връща истина, плюс
/// апостроф (`'`) и тиренце (`-`). Всичко останало е не-дума.
///
impl<'a> Iterator for WordIterator<'a> {
    type Item = (&'a str, SegmentType);

    fn next(&mut self) -> Option<Self::Item> {
        unimplemented!()
    }
}

Примерно използване на итератора може да изглежда така:

let items: Vec<_> = WordIterator::new("foo, bar").collect();

assert_eq!(
    items,
    vec![
        ("foo", SegmentType::Word),
        (", ", SegmentType::NonWord),
        ("bar", SegmentType::Word)
    ]
);

След като имаме този итератор, би трябвало да е сравнително лесно да имплементираме следната функция:


/// Итерираме през входа `input` и заместваме всички думи с резултата, който получаваме от
/// извикването на функцията. Частите, които са не-думи ги добавяме в крайния низ непромемени.
///
pub fn replace_words<F: Fn(&str) -> String>(input: &str, f: F) -> String {
    unimplemented!()
}

Примерно извикване на тази функция:

let input = "foo, bar";
let bracketed = replace_words(input, |w| format!("({})", w));

assert_eq!(bracketed, "(foo), (bar)");

Решения

Андрей
  • Коректно
  • 4 успешни тест(а)
  • 0 неуспешни тест(а)
Андрей

pub struct WordIterator<'a> {
source: &'a str,
state: Option<SegmentType>,
}
impl<'a> WordIterator<'a> {
pub fn new(source: &'a str) -> Self {
WordIterator { source, state: None }
}
fn is_word_char(c: char) -> bool {
c.is_alphabetic() || c == '\'' || c == '-'
}
}
#[derive(Debug, PartialEq)]
pub enum SegmentType {
Word,
NonWord,
}
impl<'a> Iterator for WordIterator<'a> {
type Item = (&'a str, SegmentType);
fn next(&mut self) -> Option<Self::Item> {
let mut current_index = 0;
for c in self.source.chars() {
match self.state {
None => {
if Self::is_word_char(c) {
self.state = Some(SegmentType::Word)
} else {
self.state = Some(SegmentType::NonWord)
}
},
Some(SegmentType::NonWord) if Self::is_word_char(c) => {
let segment = &self.source[0..current_index];
self.source = &self.source[current_index..];
self.state = Some(SegmentType::Word);
return Some((segment, SegmentType::NonWord));
},
Some(SegmentType::Word) if !Self::is_word_char(c) => {
let segment = &self.source[0..current_index];
self.source = &self.source[current_index..];
self.state = Some(SegmentType::NonWord);
return Some((segment, SegmentType::Word));
},
_ => (),
}
current_index += c.len_utf8();
}
let last_state = self.state.take()?;
if current_index > 0 {
Some((std::mem::take(&mut self.source), last_state))
} else {
None
}
}
}
pub fn replace_words<F: Fn(&str) -> String>(input: &str, f: F) -> String {
let mut output = String::with_capacity(input.len());
for (segment, segment_type) in WordIterator::new(input) {
match segment_type {
SegmentType::Word => output.push_str(&f(segment)),
SegmentType::NonWord => output.push_str(segment),
}
}
output
}
Compiling solution v0.1.0 (/tmp/d20200116-2173579-1a60f68/solution)
    Finished test [unoptimized + debuginfo] target(s) in 1.83s
     Running target/debug/deps/solution-a73e64ec87929bd0

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-38971695424b36d5

running 4 tests
test solution_test::test_replace ... ok
test solution_test::test_word_iterator_ascii ... ok
test solution_test::test_word_iterator_cyrillic ... ok
test solution_test::test_word_iterator_special_characters ... ok

test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests solution

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Антонио Миндов
  • Коректно
  • 4 успешни тест(а)
  • 0 неуспешни тест(а)
Антонио Миндов

pub struct WordIterator<'a> {
source: &'a str,
current_segment: SegmentType
}
fn is_from_word(c: char) -> bool {
c.is_alphabetic() || "'-".contains(c)
}
impl<'a> WordIterator<'a> {
pub fn new(source: &'a str) -> Self {
use SegmentType::*;
source.chars().next().map(|c| {
WordIterator { source, current_segment: if is_from_word(c) { Word } else { NonWord }}
}).unwrap_or(WordIterator{source, current_segment: NonWord})
}
fn swap_type(&mut self) -> SegmentType {
use SegmentType::*;
match self.current_segment {
Word => {
self.current_segment = NonWord;
Word
},
NonWord => {
self.current_segment = Word;
NonWord
}
}
}
}
#[derive(Debug, PartialEq)]
pub enum SegmentType {
Word,
NonWord
}
impl<'a> Iterator for WordIterator<'a> {
type Item = (&'a str, SegmentType);
fn next(&mut self) -> Option<Self::Item> {
if self.source.is_empty() {
return None
}
let pos = if self.current_segment == SegmentType::Word {
self.source.find(|c| !is_from_word(c))
} else {
self.source.find(is_from_word)
};
//Disappointed you can't use self.source in destructuring
let (fragment, rest) = self.source.split_at(pos.unwrap_or(self.source.len()));
self.source = rest;
Some((fragment, self.swap_type()))
}
}
pub fn replace_words<F: Fn(&str) -> String>(input: &str, f: F) -> String {
WordIterator::new(input).map(|(word, seg_type)| match seg_type {
SegmentType::Word => f(word),
SegmentType::NonWord => String::from(word)
}).collect::<Vec<_>>().join("")
}
Compiling solution v0.1.0 (/tmp/d20200116-2173579-tvrugw/solution)
    Finished test [unoptimized + debuginfo] target(s) in 2.36s
     Running target/debug/deps/solution-a73e64ec87929bd0

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-38971695424b36d5

running 4 tests
test solution_test::test_replace ... ok
test solution_test::test_word_iterator_ascii ... ok
test solution_test::test_word_iterator_cyrillic ... ok
test solution_test::test_word_iterator_special_characters ... ok

test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests solution

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Мирослав Лалев
  • Коректно
  • 4 успешни тест(а)
  • 0 неуспешни тест(а)
Мирослав Лалев

pub struct WordIterator<'a> {
source: &'a str,
}
impl<'a> WordIterator<'a> {
pub fn new(source: &'a str) -> Self {
WordIterator { source }
}
pub fn consume_next(&mut self) -> Option<(&'a str, SegmentType)> {
if self.source.len() == 0 {
return None;
}
let consume_type = SegmentType::from_char(self.source.chars().next()?);
let mut mid = 0;
for c in self.source.chars() {
let c_type = SegmentType::from_char(c);
if c_type != consume_type {
break;
}
mid += c.len_utf8();
}
let (ret, rem) = self.source.split_at(mid);
self.source = rem;
Some((ret, consume_type))
}
}
#[derive(Debug, PartialEq)]
pub enum SegmentType {
Word,
NonWord,
}
impl SegmentType {
pub fn from_char(c: char) -> SegmentType {
if c.is_alphabetic() || c == '-' || c == '\'' {
SegmentType::Word
} else {
SegmentType::NonWord
}
}
}
impl<'a> Iterator for WordIterator<'a> {
type Item = (&'a str, SegmentType);
fn next(&mut self) -> Option<Self::Item> {
self.consume_next()
}
}
pub fn replace_words<F: Fn(&str) -> String>(input: &str, f: F) -> String {
let mut res = String::new();
let mut iter = WordIterator::new(input);
while let Some((seq, seq_type)) = iter.next() {
res = format!("{}{}", res, match seq_type {
SegmentType::Word => f(seq),
SegmentType::NonWord => String::from(seq),
});
};
res
}
#[cfg(test)]
mod tests {
use super::*;
use std::ptr::replace;
#[test]
fn test_iteration() {
let words = WordIterator::new("abcd e-g g'h").collect::<Vec<_>>();
assert_eq!(words, vec![
("abcd", SegmentType::Word),
(" ", SegmentType::NonWord),
("e-g", SegmentType::Word),
(" ", SegmentType::NonWord),
("g'h", SegmentType::Word),
]);
}
#[test]
fn test_replace_words() {
let underscored = replace_words("ab c-d e'f", |w| format!("_{}_", w));
assert_eq!(underscored, "_ab_ _c-d_ _e'f_");
}
#[test]
fn test_replace_words_unicode() {
let underscored = replace_words("аб в-г д'е", |w| format!("_{}_", w));
assert_eq!(underscored, "_аб_ _в-г_ _д'е_");
}
}
Compiling solution v0.1.0 (/tmp/d20200116-2173579-9cm2qn/solution)
warning: unused import: `std::ptr::replace`
  --> src/lib.rs:72:9
   |
72 |     use std::ptr::replace;
   |         ^^^^^^^^^^^^^^^^^
   |
   = note: `#[warn(unused_imports)]` on by default

    Finished test [unoptimized + debuginfo] target(s) in 2.60s
     Running target/debug/deps/solution-a73e64ec87929bd0

running 3 tests
test tests::test_iteration ... ok
test tests::test_replace_words ... ok
test tests::test_replace_words_unicode ... ok

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-38971695424b36d5

running 4 tests
test solution_test::test_replace ... ok
test solution_test::test_word_iterator_ascii ... ok
test solution_test::test_word_iterator_cyrillic ... ok
test solution_test::test_word_iterator_special_characters ... ok

test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests solution

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Стефан Чолаков
  • Некоректно
  • 2 успешни тест(а)
  • 2 неуспешни тест(а)
Стефан Чолаков

pub struct WordIterator<'a> {
source: &'a str,
position: usize,
}
impl<'a> WordIterator<'a> {
pub fn new(source: &'a str) -> Self {
WordIterator{source,position:0}
}
}
#[derive(Debug, PartialEq)]
pub enum SegmentType {
Word,
NonWord,
}
fn is_char_word(c: &char)->bool{
c.is_alphabetic() || *c=='\'' || *c == '-'
}
impl<'a> Iterator for WordIterator<'a> {
type Item = (&'a str, SegmentType);
fn next(&mut self) -> Option<Self::Item> {
if self.position == self.source.len() {
return None;
}
let current_char = self.source[self.position.. self.position+1].chars().next().unwrap();
let mut is_word = is_char_word(&current_char);
let position = self.position;
if is_word{
while self.position<self.source.len() && is_word {
let current_char = self.source[self.position.. self.position+1].chars().next().unwrap();
is_word = is_char_word(&current_char);
if !is_word {
break;
}
self.position+=1;
}
let result = &self.source[position..self.position];
return Some((result,SegmentType::Word))
}else{
while self.position<self.source.len() && !is_word {
let current_char = self.source[self.position.. self.position+1].chars().next().unwrap();
is_word = is_char_word(&current_char);
if is_word {
break;
}
self.position+=1;
}
let result = &self.source[position..self.position];
return Some((result,SegmentType::NonWord))
}
}
}
pub fn replace_words<F: Fn(&str) -> String>(input: &str, f: F) -> String {
let mut iterator = WordIterator::new(input);
let mut result = String::new();
let mut next = iterator.next();
while next != None {
let tuple = next.unwrap();
if tuple.1 == SegmentType::Word {
let corrected = f(tuple.0);
result.push_str(&corrected);
}else{
result.push_str(&tuple.0);
}
next = iterator.next();
}
result
}
Compiling solution v0.1.0 (/tmp/d20200116-2173579-6zf004/solution)
    Finished test [unoptimized + debuginfo] target(s) in 1.84s
     Running target/debug/deps/solution-a73e64ec87929bd0

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-38971695424b36d5

running 4 tests
test solution_test::test_replace ... FAILED
test solution_test::test_word_iterator_ascii ... ok
test solution_test::test_word_iterator_cyrillic ... FAILED
test solution_test::test_word_iterator_special_characters ... ok

failures:

---- solution_test::test_replace stdout ----
thread 'main' panicked at 'byte index 1 is not a char boundary; it is inside 'Ч' (bytes 0..2) of `Честита нова година!`', src/libcore/str/mod.rs:2068:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

---- solution_test::test_word_iterator_cyrillic stdout ----
thread 'main' panicked at 'byte index 1 is not a char boundary; it is inside 'а' (bytes 0..2) of `ала, бала, ница`', src/libcore/str/mod.rs:2068:5


failures:
    solution_test::test_replace
    solution_test::test_word_iterator_cyrillic

test result: FAILED. 2 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out

error: test failed, to rerun pass '--test solution_test'
Стоян Ефтимов
  • Некоректно
  • 2 успешни тест(а)
  • 2 неуспешни тест(а)
Стоян Ефтимов

use crate::SegmentType::{NonWord, Word};
pub struct WordIterator<'a> {
source: &'a str,
current: SegmentType,
}
impl<'a> WordIterator<'a> {
pub fn new(source: &'a str) -> Self {
let current = match source.chars().next() {
None => NonWord,
Some(ch) => match WordIterator::char_in_word(&ch) {
true => Word,
false => NonWord,
}
};
Self {
source,
current,
}
}
fn char_in_word(&ch: &char) -> bool {
char::is_alphabetic(ch) || ch == '\'' || ch == '-'
}
fn next_item(&mut self, while_fn: &dyn Fn(&char) -> bool) -> &'a str {
let word_size = self.source.chars().take_while( while_fn).count();
let result = &self.source[..word_size];
self.source = &self.source[word_size..];
result
}
}
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum SegmentType {
Word,
NonWord,
}
impl<'a> Iterator for WordIterator<'a> {
type Item = (&'a str, SegmentType);
fn next(&mut self) -> Option<Self::Item> {
let current = self.current;
let next = match current {
Word => {
self.current = NonWord;
self.next_item(&Self::char_in_word)
},
NonWord => {
self.current = Word;
self.next_item(&|ch: &char| !Self::char_in_word(ch))
},
};
match next {
"" => None,
_ => Some((next, current)),
}
}
}
pub fn replace_words<F: Fn(&str) -> String>(input: &str, f: F) -> String {
WordIterator::new(input).map(|(word, segment)| {
match segment {
Word => f(word),
NonWord => String::from(word),
}
}).collect::<String>()
}
#[test]
fn test_word_iter1() {
let items: Vec<_> = WordIterator::new("12 foo, bar").collect();
assert_eq!(items, vec![
("12 ", NonWord),
("foo", Word),
(", ", NonWord),
("bar", Word)
]);
}
#[test]
fn test_word_iter2() {
let items: Vec<_> = WordIterator::new("What's the time?").collect();
assert_eq!(items, vec![
("What's", Word),
(" ", NonWord),
("the", Word),
(" ", NonWord),
("time", Word),
("?", NonWord),
]);
}
#[test]
fn test_word_iter3() {
let items: Vec<_> = WordIterator::new("It's 3 o'clock").collect();
assert_eq!(items, vec![
("It's", Word),
(" 3 ", NonWord),
("o'clock", Word),
]);
}
#[test]
fn test_word_iter4() {
assert_eq!(WordIterator::new("word").collect::<Vec<_>>(), vec![("word", Word)]);
assert_eq!(WordIterator::new("1 2 3").collect::<Vec<_>>(), vec![("1 2 3", NonWord)]);
assert_eq!(WordIterator::new("").collect::<Vec<_>>(), vec![]);
}
#[test]
fn test_replace() {
assert_eq!(replace_words("foo, bar", |w| format!("({})", w)), "(foo), (bar)");
}
Compiling solution v0.1.0 (/tmp/d20200116-2173579-1huuf3k/solution)
    Finished test [unoptimized + debuginfo] target(s) in 3.11s
     Running target/debug/deps/solution-a73e64ec87929bd0

running 5 tests
test test_replace ... ok
test test_word_iter1 ... ok
test test_word_iter2 ... ok
test test_word_iter3 ... ok
test test_word_iter4 ... ok

test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-38971695424b36d5

running 4 tests
test solution_test::test_replace ... FAILED
test solution_test::test_word_iterator_ascii ... ok
test solution_test::test_word_iterator_cyrillic ... FAILED
test solution_test::test_word_iterator_special_characters ... ok

failures:

---- solution_test::test_replace stdout ----
thread 'main' panicked at 'byte index 7 is not a char boundary; it is inside 'т' (bytes 6..8) of `Честита нова година!`', src/libcore/str/mod.rs:2068:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

---- solution_test::test_word_iterator_cyrillic stdout ----
thread 'main' panicked at 'byte index 3 is not a char boundary; it is inside 'л' (bytes 2..4) of `ала, бала, ница`', src/libcore/str/mod.rs:2068:5


failures:
    solution_test::test_replace
    solution_test::test_word_iterator_cyrillic

test result: FAILED. 2 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out

error: test failed, to rerun pass '--test solution_test'
Ангел Беширов
  • Коректно
  • 4 успешни тест(а)
  • 0 неуспешни тест(а)
Ангел Беширов

pub struct WordIterator<'a> {
source: &'a str,
current_position: usize,
current_position_byte: usize,
}
impl<'a> WordIterator<'a> {
pub fn new(source: &'a str) -> Self {
WordIterator {
source: source,
current_position: 0,
current_position_byte: 0,
}
}
}
#[derive(Debug, PartialEq)]
pub enum SegmentType {
Word,
NonWord,
}
impl<'a> Iterator for WordIterator<'a> {
type Item = (&'a str, SegmentType);
fn next(&mut self) -> Option<Self::Item> {
let mut chars: Vec<char> = self.source.chars().collect();
let len = chars.len();
if self.current_position >= len {
return None;
}
let mut next_segment: Vec<char> = Vec::new();
let seg_type: SegmentType = {
let c = chars[self.current_position];
if c.is_alphabetic() || c == '\'' || c == '-' {
SegmentType::Word
} else {
SegmentType::NonWord
}
};
let mut byte_index_end: usize = self.current_position_byte;
let mut end_index: usize = self.current_position;
for index in self.current_position..len {
let c = chars[index];
if seg_type == SegmentType::Word && (c.is_alphabetic() || c == '\'' || c == '-') {
end_index = end_index + 1;
byte_index_end = byte_index_end + c.len_utf8();
} else if seg_type == SegmentType::Word && !c.is_alphabetic() && c != '\'' && c != '-' {
break;
} else if seg_type == SegmentType::NonWord && (c.is_alphabetic() || c == '\'' || c == '-') {
break;
} else if seg_type == SegmentType::NonWord && !c.is_alphabetic() && c != '\'' && c != '-' {
end_index = end_index + 1;
byte_index_end = byte_index_end + c.len_utf8();
}
}
let start_index: usize = self.current_position;
let mut byte_index_start: usize = self.current_position_byte;
self.current_position = end_index;
self.current_position_byte = byte_index_end;
let s = self.source[byte_index_start..byte_index_end].to_string();
Some((&self.source[byte_index_start..byte_index_end], seg_type))
}
}
pub fn replace_words<F: Fn(&str) -> String>(input: &str, f: F) -> String {
let word_iterator: WordIterator = WordIterator::new(input);
let mut result: String = String::new();
for element in word_iterator {
if element.1 == SegmentType::Word {
result.push_str(&f(element.0));
} else {
result.push_str(element.0);
}
}
result
}
Compiling solution v0.1.0 (/tmp/d20200116-2173579-j6vd77/solution)
warning: unused variable: `next_segment`
  --> src/lib.rs:33:17
   |
33 |         let mut next_segment: Vec<char> = Vec::new();
   |                 ^^^^^^^^^^^^ help: consider prefixing with an underscore: `_next_segment`
   |
   = note: `#[warn(unused_variables)]` on by default

warning: unused variable: `start_index`
  --> src/lib.rs:64:13
   |
64 |         let start_index: usize = self.current_position;
   |             ^^^^^^^^^^^ help: consider prefixing with an underscore: `_start_index`

warning: unused variable: `s`
  --> src/lib.rs:68:13
   |
68 |         let s = self.source[byte_index_start..byte_index_end].to_string();
   |             ^ help: consider prefixing with an underscore: `_s`

warning: variable does not need to be mutable
  --> src/lib.rs:27:13
   |
27 |         let mut chars: Vec<char> = self.source.chars().collect();
   |             ----^^^^^
   |             |
   |             help: remove this `mut`
   |
   = note: `#[warn(unused_mut)]` on by default

warning: variable does not need to be mutable
  --> src/lib.rs:33:13
   |
33 |         let mut next_segment: Vec<char> = Vec::new();
   |             ----^^^^^^^^^^^^
   |             |
   |             help: remove this `mut`

warning: variable does not need to be mutable
  --> src/lib.rs:65:13
   |
65 |         let mut byte_index_start: usize = self.current_position_byte;
   |             ----^^^^^^^^^^^^^^^^
   |             |
   |             help: remove this `mut`

warning: unused variable: `next_segment`
  --> src/lib.rs:33:17
   |
33 |         let mut next_segment: Vec<char> = Vec::new();
   |                 ^^^^^^^^^^^^ help: consider prefixing with an underscore: `_next_segment`
   |
   = note: `#[warn(unused_variables)]` on by default

warning: unused variable: `start_index`
  --> src/lib.rs:64:13
   |
64 |         let start_index: usize = self.current_position;
   |             ^^^^^^^^^^^ help: consider prefixing with an underscore: `_start_index`

warning: unused variable: `s`
  --> src/lib.rs:68:13
   |
68 |         let s = self.source[byte_index_start..byte_index_end].to_string();
   |             ^ help: consider prefixing with an underscore: `_s`

warning: variable does not need to be mutable
  --> src/lib.rs:27:13
   |
27 |         let mut chars: Vec<char> = self.source.chars().collect();
   |             ----^^^^^
   |             |
   |             help: remove this `mut`
   |
   = note: `#[warn(unused_mut)]` on by default

warning: variable does not need to be mutable
  --> src/lib.rs:33:13
   |
33 |         let mut next_segment: Vec<char> = Vec::new();
   |             ----^^^^^^^^^^^^
   |             |
   |             help: remove this `mut`

warning: variable does not need to be mutable
  --> src/lib.rs:65:13
   |
65 |         let mut byte_index_start: usize = self.current_position_byte;
   |             ----^^^^^^^^^^^^^^^^
   |             |
   |             help: remove this `mut`

    Finished test [unoptimized + debuginfo] target(s) in 2.22s
     Running target/debug/deps/solution-a73e64ec87929bd0

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-38971695424b36d5

running 4 tests
test solution_test::test_replace ... ok
test solution_test::test_word_iterator_ascii ... ok
test solution_test::test_word_iterator_cyrillic ... ok
test solution_test::test_word_iterator_special_characters ... ok

test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests solution

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Петър Петров
  • Коректно
  • 4 успешни тест(а)
  • 0 неуспешни тест(а)
Петър Петров

pub struct WordIterator<'a> {
source: &'a str,
pos:usize,
num_cyrilic:usize,
}
impl<'a> WordIterator<'a> {
pub fn new(source: &'a str) -> Self {
WordIterator{source:source,pos:0,num_cyrilic:0}
}
}
#[derive(Debug, PartialEq)]
pub enum SegmentType {
Word,
NonWord,
}
impl<'a> Iterator for WordIterator<'a> {
type Item = (&'a str, SegmentType);
fn next(&mut self) -> Option<Self::Item> {
if self.source.len() <= self.pos+self.num_cyrilic {
return None
}
else {
let chars:Vec<_>=self.source.chars().collect();
let mut count=self.pos;
let start=self.pos;
let mut cyrilic=self.num_cyrilic;
if chars[count].is_alphabetic() || chars[count]=='\'' || chars[count]=='-'{
let cyrilic_before=cyrilic;
loop {
if chars.len() > count {
if chars[count].is_alphabetic() || chars[count]=='\'' || chars[count]=='-' {
if chars[count].len_utf8()>1 {
cyrilic=cyrilic+1;
}
count=count+1;
}
else {
break;
}
}
else{break;}
}
self.pos=count;
self.num_cyrilic=cyrilic;
Some((&self.source[start+cyrilic_before..count+cyrilic],SegmentType::Word))
}
else {
loop {
if chars.len() > count {
if !chars[count].is_alphabetic() && chars[count]!='\'' && chars[count]!='-' {
count=count+1;
}
else {
break;
}
}
else{break;}
}
self.pos=count;
Some((&self.source[start+self.num_cyrilic..count+self.num_cyrilic],SegmentType::NonWord))
}
}
}
}
pub fn replace_words<F: Fn(&str) -> String>(input: &str, f: F) -> String {
let items: Vec<_> = WordIterator::new(input).collect();
let mut word_new=String::from("");
for (word,type_of_word) in items {
if type_of_word == SegmentType::Word {
word_new.push_str(&f(word));
}
else{
word_new.push_str(word);
}
}
word_new
}
Compiling solution v0.1.0 (/tmp/d20200116-2173579-drbjw5/solution)
    Finished test [unoptimized + debuginfo] target(s) in 1.95s
     Running target/debug/deps/solution-a73e64ec87929bd0

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-38971695424b36d5

running 4 tests
test solution_test::test_replace ... ok
test solution_test::test_word_iterator_ascii ... ok
test solution_test::test_word_iterator_cyrillic ... ok
test solution_test::test_word_iterator_special_characters ... ok

test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests solution

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Димитър Иринков
  • Коректно
  • 4 успешни тест(а)
  • 0 неуспешни тест(а)
Димитър Иринков

pub struct WordIterator<'a> {
source: &'a str,
}
impl<'a> WordIterator<'a> {
pub fn new(source: &'a str) -> Self {
WordIterator {
source
}
}
}
#[derive(Debug, PartialEq)]
pub enum SegmentType {
Word,
NonWord,
}
fn is_word (c: char) -> bool {
char::is_alphabetic(c) || c == '\'' || c == '-'
}
fn not_a_word (c:char) -> bool {
!is_word(c)
}
impl<'a> Iterator for WordIterator<'a> {
type Item = (&'a str, SegmentType);
fn next(&mut self) -> Option<Self::Item> {
self.source.chars().next().map(|c| {
let segment_type;
let Pred = if is_word(c) {
segment_type = SegmentType::Word;
not_a_word
} else {
segment_type = SegmentType::NonWord;
is_word
};
let (index,_) = self.source.char_indices().find(|(byte_index, c)| Pred(*c)).unwrap_or((self.source.len(), '💜'));
let (left, right) = self.source.split_at(index);
self.source = right;
(left, segment_type)
})
}
}
pub fn replace_words<F: Fn(&str) -> String>(input: &str, f: F) -> String {
let mut s = String::with_capacity(input.len());
for (word,segment) in WordIterator::new(input) {
match segment {
SegmentType::Word => s.push_str(&f(word)),
SegmentType::NonWord => s.push_str(word),
}
}
s
}
Compiling solution v0.1.0 (/tmp/d20200116-2173579-p2dyvw/solution)
warning: unused variable: `byte_index`
  --> src/lib.rs:40:63
   |
40 |             let (index,_) = self.source.char_indices().find(|(byte_index, c)| Pred(*c)).unwrap_or((self.source.len(), '💜'));
   |                                                               ^^^^^^^^^^ help: consider prefixing with an underscore: `_byte_index`
   |
   = note: `#[warn(unused_variables)]` on by default

warning: variable `Pred` should have a snake case name
  --> src/lib.rs:33:17
   |
33 |             let Pred = if is_word(c) {
   |                 ^^^^ help: convert the identifier to snake case: `pred`
   |
   = note: `#[warn(non_snake_case)]` on by default

warning: unused variable: `byte_index`
  --> src/lib.rs:40:63
   |
40 |             let (index,_) = self.source.char_indices().find(|(byte_index, c)| Pred(*c)).unwrap_or((self.source.len(), '💜'));
   |                                                               ^^^^^^^^^^ help: consider prefixing with an underscore: `_byte_index`
   |
   = note: `#[warn(unused_variables)]` on by default

warning: variable `Pred` should have a snake case name
  --> src/lib.rs:33:17
   |
33 |             let Pred = if is_word(c) {
   |                 ^^^^ help: convert the identifier to snake case: `pred`
   |
   = note: `#[warn(non_snake_case)]` on by default

    Finished test [unoptimized + debuginfo] target(s) in 1.75s
     Running target/debug/deps/solution-a73e64ec87929bd0

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-38971695424b36d5

running 4 tests
test solution_test::test_replace ... ok
test solution_test::test_word_iterator_ascii ... ok
test solution_test::test_word_iterator_cyrillic ... ok
test solution_test::test_word_iterator_special_characters ... ok

test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests solution

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Любослав Карев
  • Коректно
  • 4 успешни тест(а)
  • 0 неуспешни тест(а)
Любослав Карев

use std::env::current_exe;
/// Забележете, че полето `source` не е публично, но сме го сложили, за да се компилира празния код
/// -- итератора е свързан по lifetime с низа, с който се вика.
///
/// Свободни сте да добавите още полета, ако ви трябват (вероятно ще ви трябват).
///
pub struct WordIterator<'a> {
source: &'a str,
current_word_end: usize,
is_looking_for_non_word: bool,
}
impl<'a> WordIterator<'a> {
pub fn new(source: &'a str) -> Self {
WordIterator {
source,
current_word_end: 0,
is_looking_for_non_word: true,
}
}
}
/// Този тип описва какъв вид текст връща итератора. Детайли по-долу.
///
#[derive(Debug, PartialEq)]
pub enum SegmentType {
Word,
NonWord,
}
/// Итератора ще връща двойка низ и типа на този низ -- дали е дума или не-дума. Целта е да
/// итерираме по целия низ, на части.
///
/// Символ, който е част от "дума" e всеки, за което `char::is_alphabetic` връща истина, плюс
/// апостроф (`'`) и тиренце (`-`). Всичко останало е не-дума.
///
impl<'a> Iterator for WordIterator<'a> {
type Item = (&'a str, SegmentType);
fn next(&mut self) -> Option<Self::Item> {
let letters: Vec<char> = self.source.chars().collect();
if self.source.len() > 0 {
for letter in self.source.chars() {
if self.is_looking_for_non_word {
if letter.is_alphabetic() || letter == '\'' || letter == '-' {
self.current_word_end += letter.len_utf8();
} else {
self.is_looking_for_non_word = false;
break;
}
}
else{
if !(letter.is_alphabetic() || letter == '\'' || letter == '-') {
self.current_word_end += letter.len_utf8();
} else {
self.is_looking_for_non_word = true;
break;
}
}
if self.current_word_end == self.source.len(){
self.is_looking_for_non_word = !self.is_looking_for_non_word;
}
}
let splitted: (&str, &str) = self.source.split_at(self.current_word_end);
self.source = splitted.1;
self.current_word_end = 0;
if self.is_looking_for_non_word == false{
Some((splitted.0, SegmentType::Word))
}
else{
Some((splitted.0, SegmentType::NonWord))
}
} else {
None
}
}
}
/// Итерираме през входа `input` и заместваме всички думи с резултата, който получаваме от
/// извикването на функцията. Частите, които са не-думи ги добавяме в крайния низ непромемени.
///
pub fn replace_words<F: Fn(&str) -> String>(input: &str, f: F) -> String {
let words = WordIterator::new(input);
let mut result = String::from("");
for word in words{
if word.1 == SegmentType::Word{
result.push_str(f(word.0).as_str());
}
else{
result.push_str(word.0);
}
}
result
}
#[cfg(test)]
mod tests {
use crate::*;
#[test]
fn test_replace_words() {
let input = "foo, bar";
let bracketed = replace_words(input, |w| format!("({})", w));
assert_eq!(bracketed, "(foo), (bar)");
}
#[test]
fn test_replace_words_cyrillic() {
let input = "фоо, бар";
let bracketed = replace_words(input, |w| format!("({})", w));
assert_eq!(bracketed, "(фоо), (бар)");
}
#[test]
fn test_replace_words_advanced() {
let input = "foo, bar-, ,baz'z";
let bracketed = replace_words(input, |w| format!("({})", w));
assert_eq!(bracketed, "(foo), (bar-), ,(baz'z)");
}
#[test]
fn test_iterator() {
let items: Vec<_> = WordIterator::new("foo, bar").collect();
assert_eq!(
items,
vec![
("foo", SegmentType::Word),
(", ", SegmentType::NonWord),
("bar", SegmentType::Word)
]
);
}
#[test]
fn test_iterator_2() {
let items: Vec<_> = WordIterator::new("foo, bar-, ,baz'z").collect();
assert_eq!(
items,
vec![
("foo", SegmentType::Word),
(", ", SegmentType::NonWord),
("bar-", SegmentType::Word),
(", ,", SegmentType::NonWord),
("baz'z", SegmentType::Word)
]
);
}
#[test]
fn test_iterator_cyrillic() {
let items: Vec<_> = WordIterator::new("фоо, бар").collect();
assert_eq!(
items,
vec![
("фоо", SegmentType::Word),
(", ", SegmentType::NonWord),
("бар", SegmentType::Word)
]
);
}
}
Compiling solution v0.1.0 (/tmp/d20200116-2173579-1nylbuc/solution)
warning: unused import: `std::env::current_exe`
 --> src/lib.rs:1:5
  |
1 | use std::env::current_exe;
  |     ^^^^^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

warning: unused variable: `letters`
  --> src/lib.rs:42:13
   |
42 |         let letters: Vec<char> = self.source.chars().collect();
   |             ^^^^^^^ help: consider prefixing with an underscore: `_letters`
   |
   = note: `#[warn(unused_variables)]` on by default

warning: unused import: `std::env::current_exe`
 --> src/lib.rs:1:5
  |
1 | use std::env::current_exe;
  |     ^^^^^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

warning: unused variable: `letters`
  --> src/lib.rs:42:13
   |
42 |         let letters: Vec<char> = self.source.chars().collect();
   |             ^^^^^^^ help: consider prefixing with an underscore: `_letters`
   |
   = note: `#[warn(unused_variables)]` on by default

    Finished test [unoptimized + debuginfo] target(s) in 2.59s
     Running target/debug/deps/solution-a73e64ec87929bd0

running 6 tests
test tests::test_iterator ... ok
test tests::test_iterator_2 ... ok
test tests::test_iterator_cyrillic ... ok
test tests::test_replace_words ... ok
test tests::test_replace_words_advanced ... ok
test tests::test_replace_words_cyrillic ... ok

test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-38971695424b36d5

running 4 tests
test solution_test::test_replace ... ok
test solution_test::test_word_iterator_ascii ... ok
test solution_test::test_word_iterator_cyrillic ... ok
test solution_test::test_word_iterator_special_characters ... ok

test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests solution

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Йоан Стоянов
  • Некоректно
  • 2 успешни тест(а)
  • 2 неуспешни тест(а)
Йоан Стоянов

pub fn replace_words<F: Fn(&str) -> String>(input: &str, f: F) -> String {
let iter = WordIterator::new(input);
let result = iter
.map(|x| {
if x.1 == SegmentType::Word {f(x.0)}
else {String::from(x.0)}
})
.fold(String::new(), |acc, x| acc + &x);
result
}
pub struct WordIterator<'a> {
source: &'a str,
current: usize,
}
impl<'a> WordIterator<'a> {
pub fn new(source: &'a str) -> Self {
WordIterator{source, current: 0}
}
}
#[derive(Debug, PartialEq)]
pub enum SegmentType {
Word,
NonWord,
}
impl<'a> Iterator for WordIterator<'a> {
type Item = (&'a str, SegmentType);
fn next(&mut self) -> Option<Self::Item> {
let mut iter = self.source.chars().skip(self.current);
let start = self.current;
let mut item;
match iter.next() {
Some(x) => item = x,
None => return None,
}
while (item.is_alphabetic() || item =='\''|| item =='-') && self.current < self.source.len() {
self.current +=1;
match iter.next(){
Some(x) => item = x,
None => break,
}
}
if self.current != start {
return Some((&self.source[start..self.current], SegmentType::Word))
}
while !item.is_alphabetic() && self.current < self.source.len() {
self.current +=1;
match iter.next(){
Some(x) => item = x,
None => break,
}
}
return Some((&self.source[start..self.current], SegmentType::NonWord))
}
}
Compiling solution v0.1.0 (/tmp/d20200116-2173579-1jwqmuk/solution)
    Finished test [unoptimized + debuginfo] target(s) in 1.81s
     Running target/debug/deps/solution-a73e64ec87929bd0

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-38971695424b36d5

running 4 tests
test solution_test::test_replace ... FAILED
test solution_test::test_word_iterator_ascii ... ok
test solution_test::test_word_iterator_cyrillic ... FAILED
test solution_test::test_word_iterator_special_characters ... ok

failures:

---- solution_test::test_replace stdout ----
thread 'main' panicked at 'byte index 7 is not a char boundary; it is inside 'т' (bytes 6..8) of `Честита нова година!`', src/libcore/str/mod.rs:2068:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

---- solution_test::test_word_iterator_cyrillic stdout ----
thread 'main' panicked at 'byte index 3 is not a char boundary; it is inside 'л' (bytes 2..4) of `ала, бала, ница`', src/libcore/str/mod.rs:2068:5


failures:
    solution_test::test_replace
    solution_test::test_word_iterator_cyrillic

test result: FAILED. 2 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out

error: test failed, to rerun pass '--test solution_test'
Георги Петков
  • Некоректно
  • 2 успешни тест(а)
  • 2 неуспешни тест(а)
Георги Петков

/// Забележете, че полето `source` не е публично, но сме го сложили, за да се компилира празния код
/// -- итератора е свързан по lifetime с низа, с който се вика.
///
/// Свободни сте да добавите още полета, ако ви трябват (вероятно ще ви трябват).
///
pub struct WordIterator<'a> {
source: &'a str,
curr: usize,
}
impl<'a> WordIterator<'a> {
pub fn new(source: &'a str) -> Self {
WordIterator { source: source, curr: 0 }
}
}
/// Този тип описва какъв вид текст връща итератора. Детайли по-долу.
///
#[derive(Debug, PartialEq)]
pub enum SegmentType {
Word,
NonWord,
}
pub fn char_type (c: char) -> SegmentType {
if c.is_alphabetic() || c=='\'' || c=='-' {
return SegmentType::Word;
} else {
return SegmentType::NonWord;
}
}
/// Итератора ще връща двойка низ и типа на този низ -- дали е дума или не-дума. Целта е да
/// итерираме по целия низ, на части.
///
/// Символ, който е част от "дума" e всеки, за което `char::is_alphabetic` връща истина, плюс
/// апостроф (`'`) и тиренце (`-`). Всичко останало е не-дума.
///
impl<'a> Iterator for WordIterator<'a> {
type Item = (&'a str, SegmentType);
fn next(&mut self) -> Option<Self::Item> {
let start = self.curr;
let len = self.source.len();
if start >= len-1 {
return None;
}
let slice = &self.source[start..len];
let mut iter = slice.char_indices();
let (_, ch) = iter.next().unwrap();
let ch_type = char_type(ch);
for (i, ch) in iter {
let curr_ch_type = char_type(ch);
if ch_type != curr_ch_type {
self.curr = i + start;
return Some((&self.source[start..(start+i)], ch_type));
}
}
self.curr = len-1;
Some((&self.source[start..len], ch_type))
}
}
pub fn replace_words<F: Fn(&str) -> String>(input: &str, f: F) -> String {
let mut s = String::new();
for (slice, slice_type) in WordIterator::new(input) {
if slice_type == SegmentType::Word {
let corrected = f(slice);
s.push_str(corrected.as_str());
} else {
s.push_str(slice);
}
}
s
}
Compiling solution v0.1.0 (/tmp/d20200116-2173579-j8cqlo/solution)
    Finished test [unoptimized + debuginfo] target(s) in 2.05s
     Running target/debug/deps/solution-a73e64ec87929bd0

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-38971695424b36d5

running 4 tests
test solution_test::test_replace ... FAILED
test solution_test::test_word_iterator_ascii ... ok
test solution_test::test_word_iterator_cyrillic ... ok
test solution_test::test_word_iterator_special_characters ... FAILED

failures:

---- solution_test::test_replace stdout ----
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `"(It\'s) (a) (beautiful) (first-of-january) (outside)"`,
 right: `"(It\'s) (a) (beautiful) (first-of-january) (outside)!"`', tests/solution_test.rs:46:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

---- solution_test::test_word_iterator_special_characters stdout ----
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `[("It\'s", Word), (" ", NonWord), ("a", Word), (" ", NonWord), ("beautiful", Word), (" ", NonWord), ("first-of-january", Word), (" ", NonWord), ("outside", Word)]`,
 right: `[("It\'s", Word), (" ", NonWord), ("a", Word), (" ", NonWord), ("beautiful", Word), (" ", NonWord), ("first-of-january", Word), (" ", NonWord), ("outside", Word), ("!", NonWord)]`', tests/solution_test.rs:27:5


failures:
    solution_test::test_replace
    solution_test::test_word_iterator_special_characters

test result: FAILED. 2 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out

error: test failed, to rerun pass '--test solution_test'
Иво Стефанов
  • Коректно
  • 4 успешни тест(а)
  • 0 неуспешни тест(а)
Иво Стефанов

use std::str;
/// Забележете, че полето `source` не е публично, но сме го сложили, за да се компилира празния код
/// -- итератора е свързан по lifetime с низа, с който се вика.
///
/// Свободни сте да добавите още полета, ако ви трябват (вероятно ще ви трябват).
///
pub struct WordIterator<'a> {
source: &'a str,
}
impl<'a> WordIterator<'a> {
pub fn new(source: &'a str) -> Self {
WordIterator{source : source}
}
}
/// Този тип описва какъв вид текст връща итератора. Детайли по-долу.
///
#[derive(Debug, PartialEq)]
pub enum SegmentType {
Word,
NonWord,
}
/// Итератора ще връща двойка низ и типа на този низ -- дали е дума или не-дума. Целта е да
/// итерираме по целия низ, на части.
///
/// Символ, който е част от "дума" e всеки, за което `char::is_alphabetic` връща истина, плюс
/// апостроф (`'`) и тиренце (`-`). Всичко останало е не-дума.
///
impl<'a> Iterator for WordIterator<'a> {
type Item = (&'a str, SegmentType);
fn next(&mut self) -> Option<Self::Item> {
if self.source.len() == 0 {
return None;
}
let mut typ: SegmentType = SegmentType::Word;
let mut index = 0;
let mut last_character: char = ' ';
for it in self.source.chars() {
if index == 0 {
if it.is_alphabetic() || it == '\'' || it == '-'{
typ = SegmentType::Word;
}
else {
typ = SegmentType::NonWord;
}
}
if (typ == SegmentType::Word && !(it.is_alphabetic() || it == '\'' || it == '-')) ||
(typ == SegmentType::NonWord && (it.is_alphabetic() || it == '\'' || it == '-')) {
last_character = it;
break;
}
index += 1;
}
let byte_index;
let find_res = self.source.find(last_character);
if find_res == None {
byte_index = self.source.as_bytes().len();
}
else {
byte_index = find_res.unwrap();
}
let to_return: &'a str = str::from_utf8( &(self.source.as_bytes())[..byte_index] ).unwrap();
let left_to_iterate: &'a str;
if (self.source.as_bytes())[byte_index..].len() == 0{
left_to_iterate = &("");
}
else {
left_to_iterate = str::from_utf8( &(self.source.as_bytes())[byte_index..] ).unwrap();
}
self.source = left_to_iterate;
//print!("'{}' - '{}'\n",to_return, left_to_iterate);
Some((to_return, typ))
}
}
/// Итерираме през входа `input` и заместваме всички думи с резултата, който получаваме от
/// извикването на функцията. Частите, които са не-думи ги добавяме в крайния низ непромемени.
///
pub fn replace_words<F: Fn(&str) -> String>(input: &str, f: F) -> String {
let items: Vec<_> = WordIterator::new(input).collect();
let mut string: String = String::new();
for i in 0..items.len() {
if items[i].1 == SegmentType::Word {
string.push_str(&f(items[i].0));
}
else {
string.push_str(items[i].0);
}
}
string
}
Compiling solution v0.1.0 (/tmp/d20200116-2173579-urxs5i/solution)
    Finished test [unoptimized + debuginfo] target(s) in 1.85s
     Running target/debug/deps/solution-a73e64ec87929bd0

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-38971695424b36d5

running 4 tests
test solution_test::test_replace ... ok
test solution_test::test_word_iterator_ascii ... ok
test solution_test::test_word_iterator_cyrillic ... ok
test solution_test::test_word_iterator_special_characters ... ok

test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests solution

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Катерина Манева
  • Некоректно
  • 0 успешни тест(а)
  • 0 неуспешни тест(а)
Катерина Манева

#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
mod find_errors {
use std::collections::HashMap;
use std::iter::FromIterator;
pub fn clean_line(input: &str) -> String {
input.trim().chars().filter(|c| c.is_alphabetic() || c.is_whitespace() || *c == '\'' || *c == '-').collect()
}
pub struct WordCounter {
corpus: HashMap<String, u32>,
}
impl WordCounter {
pub fn new() -> Self {
let corpus = HashMap::new();
Self{corpus: corpus}
}
pub fn from_str(input: &str) -> Self {
let mut counter = WordCounter::new();
let lines = input.lines();
for line in lines {
let cleaned_line = clean_line(line);
for word in cleaned_line.split_whitespace() {
counter.add(word);
}
}
counter
}
pub fn words(&self) -> Vec<&String> {
let mut vec = Vec::from_iter(self.corpus.keys());
vec.sort_unstable();
vec
}
pub fn add(&mut self, item: &str) {
let lowercase = item.to_lowercase();
let trimmed = lowercase.trim();
let counter = self.corpus.entry(trimmed.to_string()).or_insert(0);
*counter += 1;
}
pub fn get(&self, word: &str) -> u32 {
let value = self.corpus.get(&word.to_string());
*value.unwrap_or(&0)
}
pub fn total_count(&self) -> u32 {
self.corpus.values().sum()
}
}
impl std::fmt::Display for WordCounter {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "WordCounter, total count: {}\n", self.total_count())?;
let mut entries: Vec<(&String, &u32)> = self.corpus.iter().collect();
entries.sort_unstable_by(|a, b| b.1.cmp(a.1));
for entry in entries {
write!(f, "{}: {}\n", entry.0, entry.1)?;
}
Ok(())
}
}
use std::collections::HashSet;
/// Тези две константи са за удобство -- ще ги използваме в тестовете, свободни сте да ги
/// използвате във вашите.
pub const ALPHABET_EN: &'static str = "abcdefghijklmnopqrstuvwxyz";
pub const ALPHABET_BG: &'static str = "абвгдежзийклмнопрстуфхцчшщъьюя";
pub struct SpellChecker {
corpus: WordCounter,
alphabet: String,
}
impl SpellChecker {
pub fn new(corpus: &str, alphabet: &str) -> Self {
Self{corpus: WordCounter::from_str(corpus), alphabet: alphabet.to_string()}
}
pub fn correction(&self, word: &str) -> String {
self.candidates(word)[0].clone()
}
pub fn probability(&self, word: &str) -> f64 {
let occurances = self.corpus.get(word);
let total = self.corpus.total_count();
occurances as f64 / total as f64
}
pub fn known<'a> (&self, words: &'a HashSet<String>) -> Vec<&'a String> {
words.into_iter().filter(|w| self.corpus.get(w) > 0).collect()
}
pub fn candidates(&self, word: &str) -> Vec<String> {
if self.corpus.get(word) > 0 {
vec![word.to_string()]
} else {
let p = self.edits1(word);
let candidates_1 = self.known(&p);
if !candidates_1.is_empty() {
candidates_1.iter().map(|&s| s.clone()).collect()
} else {
let q = self.edits2(word);
let candidates_2 = self.known(&q);
if !candidates_2.is_empty() {
candidates_2.iter().map(|&s| s.clone()).collect()
} else {
vec![word.to_string()]
}
}
}
}
pub fn edits1(&self, word: &str) -> HashSet<String> {
let mut result = HashSet::new();
for i in 0.. word.len() {
let (first, last) = word.split_at(i);
result.insert([first, &last[1..]].concat());
}
for i in 0 .. word.len() - 1 {
let (first, last) = word.split_at(i);
result.insert([first, &last[1..2], &last[..1], &last[2..]].concat());
}
for i in 0 .. word.len() + 1 {
for c in self.alphabet.chars() {
let (first, last) = word.split_at(i);
let mut buffer = [0; 1];
let res = c.encode_utf8(&mut buffer);
result.insert([first, res, last].concat());
}
}
for i in 0 .. word.len() {
for c in self.alphabet.chars() {
let (first, last) = word.split_at(i);
let mut buffer = [0; 1];
let res = c.encode_utf8(&mut buffer);
result.insert([first, res, &last[1..]].concat());
}
}
result
}
pub fn edits2(&self, word: &str) -> HashSet<String> {
self.edits1(word).iter().flat_map(|word_edit_1| self.edits1(word_edit_1)).collect()
}
}
}
mod correct_errors {
pub struct WordIterator<'a> {
source: &'a str,
current_index: u32,
}
impl<'a> WordIterator<'a> {
pub fn new(source: &'a str) -> Self {
Self{source: source, current_index: 0}
}
}
#[derive(Debug, PartialEq)]
pub enum SegmentType {
Word,
NonWord,
}
impl<'a> Iterator for WordIterator<'a> {
type Item = (&'a str, SegmentType);
fn next(&mut self) -> Option<Self::Item> {
let next_index = self.current_index;
let len_source = self.source.len() as u32;
if self.current_index == len_source {
return None;
} else {
let mut result = Some(("", SegmentType::NonWord));
let sub_string;
if let Some(next_index) = self.source.find(|c: char| c.is_alphabetic() || c == '\'' || c == '-') {
sub_string = &self.source[self.current_index as usize..next_index as usize];
result = Some((sub_string, SegmentType::Word));
} else if let Some(next_index) = self.source.find(|c: char| !c.is_alphabetic() || c != '\'' || c != '-') {
sub_string = &self.source[self.current_index as usize..next_index as usize];
result = Some((sub_string, SegmentType::NonWord));
}
result
}
}
}
pub fn replace_words<F: Fn(&str) -> String>(input: &str, f: F) -> String {
let wi = WordIterator::new(input);
wi.map(|el|
if el.1 == SegmentType::Word {
f(el.0)
} else {
el.0.to_string()
}).collect()
}
}
Compiling solution v0.1.0 (/tmp/d20200116-2173579-187mrj7/solution)
warning: unused variable: `next_index`
   --> src/lib.rs:186:17
    |
186 |             let next_index = self.current_index;
    |                 ^^^^^^^^^^ help: consider prefixing with an underscore: `_next_index`
    |
    = note: `#[warn(unused_variables)]` on by default

warning: function is never used: `clean_line`
  --> src/lib.rs:13:5
   |
13 |     pub fn clean_line(input: &str) -> String {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: `#[warn(dead_code)]` on by default

warning: method is never used: `new`
  --> src/lib.rs:22:9
   |
22 |         pub fn new() -> Self {
   |         ^^^^^^^^^^^^^^^^^^^^

warning: method is never used: `from_str`
  --> src/lib.rs:27:9
   |
27 |         pub fn from_str(input: &str) -> Self {
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: method is never used: `words`
  --> src/lib.rs:39:9
   |
39 |         pub fn words(&self) -> Vec<&String> {
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: method is never used: `add`
  --> src/lib.rs:45:9
   |
45 |         pub fn add(&mut self, item: &str) {
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: method is never used: `get`
  --> src/lib.rs:54:9
   |
54 |         pub fn get(&self, word: &str) -> u32 {
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: constant item is never used: `ALPHABET_EN`
  --> src/lib.rs:80:5
   |
80 |     pub const ALPHABET_EN: &'static str = "abcdefghijklmnopqrstuvwxyz";
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: constant item is never used: `ALPHABET_BG`
  --> src/lib.rs:81:5
   |
81 |     pub const ALPHABET_BG: &'static str = "абвгдежзийклмнопрстуфхцчшщъьюя";
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: struct is never constructed: `SpellChecker`
  --> src/lib.rs:83:5
   |
83 |     pub struct SpellChecker {
   |     ^^^^^^^^^^^^^^^^^^^^^^^

warning: method is never used: `new`
  --> src/lib.rs:90:9
   |
90 |         pub fn new(corpus: &str, alphabet: &str) -> Self {
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: method is never used: `correction`
  --> src/lib.rs:94:9
   |
94 |         pub fn correction(&self, word: &str) -> String {
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: method is never used: `probability`
  --> src/lib.rs:98:9
   |
98 |         pub fn probability(&self, word: &str) -> f64 {
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: method is never used: `known`
   --> src/lib.rs:104:9
    |
104 |         pub fn known<'a> (&self, words: &'a HashSet<String>) -> Vec<&'a String> {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: method is never used: `candidates`
   --> src/lib.rs:108:9
    |
108 |         pub fn candidates(&self, word: &str) -> Vec<String> {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: method is never used: `edits1`
   --> src/lib.rs:129:9
    |
129 |         pub fn edits1(&self, word: &str) -> HashSet<String> {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: method is never used: `edits2`
   --> src/lib.rs:158:9
    |
158 |         pub fn edits2(&self, word: &str) -> HashSet<String> {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: method is never used: `new`
   --> src/lib.rs:171:9
    |
171 |         pub fn new(source: &'a str) -> Self {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: function is never used: `replace_words`
   --> src/lib.rs:205:5
    |
205 |     pub fn replace_words<F: Fn(&str) -> String>(input: &str, f: F) -> String {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: unused variable: `next_index`
   --> src/lib.rs:186:17
    |
186 |             let next_index = self.current_index;
    |                 ^^^^^^^^^^ help: consider prefixing with an underscore: `_next_index`
    |
    = note: `#[warn(unused_variables)]` on by default

warning: function is never used: `clean_line`
  --> src/lib.rs:13:5
   |
13 |     pub fn clean_line(input: &str) -> String {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: `#[warn(dead_code)]` on by default

warning: method is never used: `new`
  --> src/lib.rs:22:9
   |
22 |         pub fn new() -> Self {
   |         ^^^^^^^^^^^^^^^^^^^^

warning: method is never used: `from_str`
  --> src/lib.rs:27:9
   |
27 |         pub fn from_str(input: &str) -> Self {
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: method is never used: `words`
  --> src/lib.rs:39:9
   |
39 |         pub fn words(&self) -> Vec<&String> {
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: method is never used: `add`
  --> src/lib.rs:45:9
   |
45 |         pub fn add(&mut self, item: &str) {
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: method is never used: `get`
  --> src/lib.rs:54:9
   |
54 |         pub fn get(&self, word: &str) -> u32 {
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: constant item is never used: `ALPHABET_EN`
  --> src/lib.rs:80:5
   |
80 |     pub const ALPHABET_EN: &'static str = "abcdefghijklmnopqrstuvwxyz";
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: constant item is never used: `ALPHABET_BG`
  --> src/lib.rs:81:5
   |
81 |     pub const ALPHABET_BG: &'static str = "абвгдежзийклмнопрстуфхцчшщъьюя";
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: struct is never constructed: `SpellChecker`
  --> src/lib.rs:83:5
   |
83 |     pub struct SpellChecker {
   |     ^^^^^^^^^^^^^^^^^^^^^^^

warning: method is never used: `new`
  --> src/lib.rs:90:9
   |
90 |         pub fn new(corpus: &str, alphabet: &str) -> Self {
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: method is never used: `correction`
  --> src/lib.rs:94:9
   |
94 |         pub fn correction(&self, word: &str) -> String {
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: method is never used: `probability`
  --> src/lib.rs:98:9
   |
98 |         pub fn probability(&self, word: &str) -> f64 {
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: method is never used: `known`
   --> src/lib.rs:104:9
    |
104 |         pub fn known<'a> (&self, words: &'a HashSet<String>) -> Vec<&'a String> {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: method is never used: `candidates`
   --> src/lib.rs:108:9
    |
108 |         pub fn candidates(&self, word: &str) -> Vec<String> {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: method is never used: `edits1`
   --> src/lib.rs:129:9
    |
129 |         pub fn edits1(&self, word: &str) -> HashSet<String> {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: method is never used: `edits2`
   --> src/lib.rs:158:9
    |
158 |         pub fn edits2(&self, word: &str) -> HashSet<String> {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: method is never used: `new`
   --> src/lib.rs:171:9
    |
171 |         pub fn new(source: &'a str) -> Self {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: function is never used: `replace_words`
   --> src/lib.rs:205:5
    |
205 |     pub fn replace_words<F: Fn(&str) -> String>(input: &str, f: F) -> String {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0433]: failed to resolve: use of undeclared type or module `WordIterator`
 --> tests/solution_test.rs:9:17
  |
9 |     let parts = WordIterator::new(input).map(|(s, _)| s).collect::<Vec<_>>();
  |                 ^^^^^^^^^^^^ use of undeclared type or module `WordIterator`

error[E0433]: failed to resolve: use of undeclared type or module `WordIterator`
  --> tests/solution_test.rs:17:17
   |
17 |     let parts = WordIterator::new(input).map(|(s, _)| s).collect::<Vec<_>>();
   |                 ^^^^^^^^^^^^ use of undeclared type or module `WordIterator`

error[E0433]: failed to resolve: use of undeclared type or module `WordIterator`
  --> tests/solution_test.rs:25:17
   |
25 |     let parts = WordIterator::new(input).collect::<Vec<_>>();
   |                 ^^^^^^^^^^^^ use of undeclared type or module `WordIterator`

error[E0433]: failed to resolve: use of undeclared type or module `SegmentType`
  --> tests/solution_test.rs:28:30
   |
28 |         ("It's",             SegmentType::Word),
   |                              ^^^^^^^^^^^ use of undeclared type or module `SegmentType`

error[E0433]: failed to resolve: use of undeclared type or module `SegmentType`
  --> tests/solution_test.rs:29:30
   |
29 |         (" ",                SegmentType::NonWord),
   |                              ^^^^^^^^^^^ use of undeclared type or module `SegmentType`

error[E0433]: failed to resolve: use of undeclared type or module `SegmentType`
  --> tests/solution_test.rs:30:30
   |
30 |         ("a",                SegmentType::Word),
   |                              ^^^^^^^^^^^ use of undeclared type or module `SegmentType`

error[E0433]: failed to resolve: use of undeclared type or module `SegmentType`
  --> tests/solution_test.rs:31:30
   |
31 |         (" ",                SegmentType::NonWord),
   |                              ^^^^^^^^^^^ use of undeclared type or module `SegmentType`

error[E0433]: failed to resolve: use of undeclared type or module `SegmentType`
  --> tests/solution_test.rs:32:30
   |
32 |         ("beautiful",        SegmentType::Word),
   |                              ^^^^^^^^^^^ use of undeclared type or module `SegmentType`

error[E0433]: failed to resolve: use of undeclared type or module `SegmentType`
  --> tests/solution_test.rs:33:30
   |
33 |         (" ",                SegmentType::NonWord),
   |                              ^^^^^^^^^^^ use of undeclared type or module `SegmentType`

error[E0433]: failed to resolve: use of undeclared type or module `SegmentType`
  --> tests/solution_test.rs:34:30
   |
34 |         ("first-of-january", SegmentType::Word),
   |                              ^^^^^^^^^^^ use of undeclared type or module `SegmentType`

error[E0433]: failed to resolve: use of undeclared type or module `SegmentType`
  --> tests/solution_test.rs:35:30
   |
35 |         (" ",                SegmentType::NonWord),
   |                              ^^^^^^^^^^^ use of undeclared type or module `SegmentType`

error[E0433]: failed to resolve: use of undeclared type or module `SegmentType`
  --> tests/solution_test.rs:36:30
   |
36 |         ("outside",          SegmentType::Word),
   |                              ^^^^^^^^^^^ use of undeclared type or module `SegmentType`

error[E0433]: failed to resolve: use of undeclared type or module `SegmentType`
  --> tests/solution_test.rs:37:30
   |
37 |         ("!",                SegmentType::NonWord),
   |                              ^^^^^^^^^^^ use of undeclared type or module `SegmentType`

error[E0425]: cannot find function `replace_words` in this scope
  --> tests/solution_test.rs:44:21
   |
44 |     let bracketed = replace_words(input, |w| format!("({})", w));
   |                     ^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function `replace_words` in this scope
  --> tests/solution_test.rs:49:22
   |
49 |     let emphasized = replace_words(input, |w| format!("*{}*", w));
   |                      ^^^^^^^^^^^^^ not found in this scope

warning: unused import: `solution::*`
 --> tests/solution_test.rs:4:7
  |
4 |   use solution::*;
  |       ^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

error: aborting due to 15 previous errors

Some errors have detailed explanations: E0425, E0433.
For more information about an error, try `rustc --explain E0425`.
error: could not compile `solution`.

To learn more, run the command again with --verbose.